La respuesta que seleccionó para ser la correcta (indicada por la marca de verificación verde) es incorrecta. No define qué distingue la programación declarativa de su antítesis: programación imperativa. Por favor considere cambiar su selección.
Shelby Moore III
3
Sí, la respuesta marcada como correcta NO es correcta.
Dermot
44
@ShelbyMooreIII ¡También especifique qué respuesta es correcta para que podamos leerla!
vivek.m
@ vivek.m Hoy he proporcionado una nueva respuesta .
Shelby Moore III
Respuestas:
148
La programación declarativa es cuando escribes tu código de tal manera que describe lo que quieres hacer, y no cómo quieres hacerlo. Le corresponde al compilador averiguar el cómo.
Ejemplos de lenguajes de programación declarativos son SQL y Prolog.
Será realmente genial si puedes mencionar cómo es diferente de la programación imperativa (lenguajes como C, C ++, C #), entonces será más fácil para los lectores distinguir la diferencia.
RBT
1
programador : "Quiero viajar a París". declarativa (c) : "¿Cómo le gustaría llegar allí? ¿navegar en barco? o volar en un avión? tal vez, navegar a mitad de camino y luego volar el resto del camino?" programador : "No me interesa cómo se hace". imperativo (sql) : "No se preocupe. Puedo consultar lo que necesita". ( así es como entiendo la respuesta )
nate
¿Cómo puede ser SQL declarativo si admite expresiones que no son referencialmente transparentes?
java-addict301
80
Las otras respuestas ya hacen un trabajo fantástico al explicar qué es la programación declarativa, así que solo voy a proporcionar algunos ejemplos de por qué eso podría ser útil.
Independencia de contexto
Los programas declarativos son independientes del contexto . Debido a que solo declaran cuál es el objetivo final, pero no los pasos intermedios para alcanzar ese objetivo, se puede usar el mismo programa en diferentes contextos. Esto es difícil de hacer con los programas imperativos , porque a menudo dependen del contexto (por ejemplo, estado oculto).
Toma yacccomo ejemplo. Es un generador de analizador alias. compilador compilador, un DSL declarativo externo para describir la gramática de un idioma, de modo que se pueda generar automáticamente un analizador para ese idioma a partir de la descripción. Debido a su independencia de contexto, puede hacer muchas cosas diferentes con dicha gramática:
Genere un analizador C para esa gramática (el caso de uso original para yacc)
Generar un analizador de C ++ para esa gramática
Generar un analizador Java para esa gramática (usando Jay)
Genere un analizador C # para esa gramática (usando GPPG)
Generar un analizador Ruby para esa gramática (usando Racc)
Genere una visualización de árbol para esa gramática (usando GraphViz)
simplemente haga una impresión bonita, un formato elegante y resalte de sintaxis del archivo fuente de yacc e inclúyalo en su Manual de referencia como una especificación sintáctica de su idioma
Y muchos más …
Mejoramiento
Debido a que no prescribe a la computadora qué pasos tomar y en qué orden, puede reorganizar su programa mucho más libremente, incluso puede ejecutar algunas tareas en paralelo. Un buen ejemplo es un planificador de consultas y un optimizador de consultas para una base de datos SQL. La mayoría de las bases de datos SQL le permiten mostrar la consulta que realmente están ejecutando frente a la consulta que les pidió que ejecutaran. A menudo, esas consultas no parecen nadacomo el uno al otro. El planificador de consultas tiene en cuenta cosas que ni siquiera hubiera soñado: la latencia rotacional del disco, por ejemplo, o el hecho de que una aplicación completamente diferente para un usuario completamente diferente acaba de ejecutar una consulta similar y la tabla que usted es unirse y trabajar tan duro para evitar cargar ya está en la memoria de todos modos.
No es una disyuntiva interesante aquí: la máquina tiene que trabajar más para averiguar cómo hacer algo de lo que sería en un lenguaje imperativo, pero cuando se hace entenderlo, tiene mucha más libertad y mucha más información para la optimización etapa.
Conjuntos de declaraciones o declaraciones declarativas, cada una de las cuales tiene un significado (a menudo en el dominio del problema) y puede entenderse de forma independiente y aislada.
La programación imperativa tiende a: -
Secuencias de comandos, cada uno de los cuales realiza alguna acción; pero que puede o no tener significado en el dominio del problema.
Como resultado, un estilo imperativo ayuda al lector a comprender la mecánica de lo que realmente está haciendo el sistema, pero puede dar poca información sobre el problema que se pretende resolver. Por otro lado, un estilo declarativo ayuda al lector a comprender el dominio del problema y el enfoque que el sistema adopta para la solución del problema, pero es menos informativo sobre el tema de la mecánica.
Los programas reales (incluso los escritos en lenguajes que favorecen los extremos del espectro, como ProLog o C) tienden a tener ambos estilos presentes en varios grados en varios puntos, para satisfacer las diversas complejidades y necesidades de comunicación de la pieza. Un estilo no es superior al otro; solo sirven para diferentes propósitos y, como con muchas cosas en la vida, la moderación es la clave.
Esa es la respuesta correcta. Nada de ese murmullo anterior
Krzysztof Wende
Gracias por no solo responder la pregunta, sino también por hacerlo con el estilo "Explicar como si fuera 5" con contexto y practicidad. Excelente respuesta
Monsto
17
Aquí hay un ejemplo.
En CSS (usado para diseñar páginas HTML), si desea que un elemento de imagen tenga 100 píxeles de alto y 100 píxeles de ancho, simplemente "declara" que eso es lo que quiere de la siguiente manera:
#myImageId {
height: 100px;
width: 100px;
}
Puede considerar CSS un lenguaje declarativo de "hoja de estilo".
El motor del navegador que lee e interpreta este CSS es libre de hacer que la imagen parezca tan alta y ancha como quiera. Diferentes motores de navegador (por ejemplo, el motor para IE, el motor para Chrome) implementarán esta tarea de manera diferente.
Sus implementaciones únicas, por supuesto, NO están escritas en un lenguaje declarativo, sino en un lenguaje de procedimiento como Assembly, C, C ++, Java, JavaScript o Python. Ese código es un conjunto de pasos que se llevarán a cabo paso a paso (y puede incluir llamadas a funciones). Podría hacer cosas como interpolar valores de píxeles y renderizar en la pantalla.
Lo siento, pero debo estar en desacuerdo con muchas de las otras respuestas. Me gustaría detener este malentendido confuso de la definición de programación declarativa.
Otros atributos citados de programación declarativa, derivan de este RT. Haga clic en el hipervínculo de arriba para obtener una explicación detallada.
Ejemplo de hoja de cálculo
Dos respuestas mencionaron la programación de hojas de cálculo. En los casos en que la programación de la hoja de cálculo (también conocida como fórmulas) no accede al estado global mutable , entonces es la programación declarativa. Esto se debe a que los valores de celda mutables son la entrada y salida monolítica del main()(todo el programa). Los nuevos valores no se escriben en las celdas después de ejecutar cada fórmula, por lo que no son mutables durante la vida del programa declarativo (ejecución de todas las fórmulas en la hoja de cálculo). Por lo tanto, uno con respecto al otro, las fórmulas ven estas células mutables como inmutables. Se permite que una función RT acceda al estado global inmutable (y también al estado local mutable ).
Por lo tanto, la capacidad de mutar los valores en las celdas cuando el programa termina (como resultado de main()) no los convierte en valores almacenados mutables en el contexto de las reglas. La distinción clave es que los valores de las celdas no se actualizan después de realizar cada fórmula de hoja de cálculo, por lo tanto, el orden de ejecución de las fórmulas no importa. Los valores de las celdas se actualizan después de que se hayan realizado todas las fórmulas declarativas.
Los efectos secundarios no deseados pueden destruir la relación entre lo que se declaró y el comportamiento real del programa. Lo expliqué con más detalle en una nueva respuesta .
Shelby Moore III
8
La programación declarativa es la imagen, donde la programación imperativa son instrucciones para pintar esa imagen.
Estás escribiendo en un estilo declarativo si estás "diciéndole lo que es", en lugar de describir los pasos que la computadora debe seguir para llegar a donde quieres.
Cuando usas XML para marcar datos, estás usando programación declarativa porque estás diciendo "Esta es una persona, es un cumpleaños y allí hay una dirección".
Algunos ejemplos de donde la programación declarativa e imperativa se combinan para un mayor efecto:
Windows Presentation Foundation utiliza la sintaxis XML declarativa para describir el aspecto de una interfaz de usuario y las relaciones (enlaces) entre los controles y las estructuras de datos subyacentes.
Los archivos de configuración estructurados usan sintaxis declarativa (tan simple como pares "clave = valor") para identificar lo que significa una cadena o valor de datos.
HTML marca el texto con etiquetas que describen qué papel tiene cada parte del texto en relación con todo el documento.
Aunque XML es declarativo, no iría tan lejos como para decir que es programación declarativa simplemente porque no hay una semántica activa asociada con el marcado. Decir que algo es una dirección no ayuda a descubrir qué quiere hacer con él.
HenryR
1
Tiene que haber un contexto subyacente (dominio?) En el que se utiliza el programa declarativo. Por lo tanto, el uso de XML combinado con ANT puede interpretarse como un programa declarativo.
Gutzofter
7
La programación declarativa es la programación con declaraciones, es decir, oraciones declarativas. Las oraciones declarativas tienen una serie de propiedades que las distinguen de las oraciones imperativas. En particular, las declaraciones son:
conmutativo (puede reordenarse)
asociativo (puede reagruparse)
idempotente (puede repetirse sin cambio de significado)
monótono (las declaraciones no restan información)
Un punto relevante es que estas son todas propiedades estructurales y son ortogonales al tema. Declarativo no se trata de "Qué vs. Cómo" . Podemos declarar (representar y restringir) un "cómo" tan fácilmente como declaramos un "qué" .Declarativo se trata de estructura, no de contenido. La programación declarativa tiene un impacto significativo en cómo abstraemos y refactorizamos nuestro código, y cómo lo modularizamos en subprogramas, pero no tanto en el modelo de dominio.
A menudo, podemos convertir de imperativo a declarativo agregando contexto. Por ejemplo, "Gire a la izquierda. (... espere ...) Gire a la derecha". a "Bob girará a la izquierda en la intersección de Foo y Bar a las 11:01. Bob girará a la derecha en la intersección de Bar y Baz a las 11:06". Tenga en cuenta que en el último caso las oraciones son idempotentes y conmutativas, mientras que en el primer caso reorganizar o repetir las oraciones cambiaría severamente el significado del programa.
Con respecto a lo monótono , las declaraciones pueden agregar restricciones que restan posibilidades . Pero las restricciones aún agregan información (más precisamente, las restricciones son información). Si necesitamos declaraciones que varíen en el tiempo, es típico modelar esto con una semántica temporal explícita, por ejemplo, desde "la pelota es plana" hasta "la pelota es plana en el momento T". Si tenemos dos declaraciones contradictorias, tenemos un sistema declarativo inconsistente, aunque esto podría resolverse introduciendo restricciones blandas (prioridades, probabilidades, etc.) o aprovechando una lógica paraconsistente.
Las expresiones declarativas contribuyen al comportamiento previsto del programa, el imperativo puede contribuir a lo intencionado o no. Declarativo no necesita ser conmutativo e idempotente, si se trata de una semántica intencional.
Shelby Moore III
6
Describiendo a una computadora lo que quieres, no cómo hacer algo.
imagina una página de Excel. Con columnas pobladas con fórmulas para calcular su declaración de impuestos.
Toda la lógica se hace declarada en las celdas, el orden del cálculo se determina mediante la fórmula misma en lugar de por procedimiento.
De eso se trata la programación declarativa. Usted declara el espacio del problema y la solución en lugar del flujo del programa.
Prolog es el único lenguaje declarativo que uso. Requiere un tipo diferente de pensamiento, pero es bueno aprender si solo para exponerlo a algo que no sea el típico lenguaje de programación procesal.
He refinado mi comprensión de la programación declarativa, desde diciembre de 2011, cuando proporcioné una respuesta a esta pregunta. Aquí sigue mi comprensión actual.
La versión larga de mi comprensión (investigación) se detalla en este enlace. , que debe leer para obtener una comprensión profunda del resumen que proporcionaré a continuación.
La programación imperativa es donde se almacena y lee el estado mutable, por lo que el orden y / o la duplicación de las instrucciones del programa pueden alterar el comportamiento (semántica) del programa (e incluso causar un error, es decir, un comportamiento involuntario).
En el sentido más ingenuo y extremo (que afirmé en mi respuesta anterior), la programación declarativa (DP) está evitando todo el estado mutable almacenado, por lo tanto, ordenar y / o duplicar las instrucciones del programa NO puede alterar el comportamiento (semántica) del programa .
Sin embargo, una definición tan extrema no sería muy útil en el mundo real, ya que casi todos los programas implican un estado mutable almacenado. El ejemplo de hoja de cálculo se ajusta a esta definición extrema de DP, porque todo el código del programa se ejecuta hasta su finalización con una copia estática del estado de entrada, antes de que se almacenen los nuevos estados. Luego, si se cambia algún estado, esto se repite. Pero la mayoría de los programas del mundo real no pueden limitarse a un modelo tan monolítico de cambios de estado.
Una definición más útil de DP es que el orden y / o la duplicación de las instrucciones de programación no alteran ninguna semántica opaca. En otras palabras, no se producen cambios aleatorios ocultos en la semántica; cualquier cambio en el orden y / o duplicación de las instrucciones del programa solo causa cambios intencionados y transparentes en el comportamiento del programa.
El siguiente paso sería hablar sobre qué modelos de programación o paradigmas ayudan en DP, pero esa no es la cuestión aquí.
Actualización: consulte también la explicación más exhaustiva en mi otra respuesta sobre la definición de programación declarativa.
Shelby Moore III
Functional programminges una palabra de moda en estos días que es esencialmente un subconjunto de programación declarativa. LINQ en lenguaje C # es un elemento de programación funcional cuando el lenguaje en sí es imprescindible por naturaleza. Entonces, C # se convierte en una especie de híbrido según esa definición.
RBT
1
El enlace compute.com está muerto.
Kedar Mhaswade
5
Es un método de programación basado en describir lo que algo debe hacer o ser en lugar de describir cómo debería funcionar.
En otras palabras, no escribes algoritmos hechos de expresiones, solo diseñas cómo quieres que sean las cosas. Dos buenos ejemplos son HTML y WPF.
Menuda objeción. WPF es una biblioteca, no realmente un lenguaje o un paradigma. Creo que realmente quisiste decir que XAML es un ejemplo de lenguaje declarativo.
Nick
¿Y cómo describirías la programación usando una biblioteca / framework?
Gutzofter
Es incorrecto afirmar que la programación declarativa no puede contener expresiones. La distinción clave es que las expresiones no pueden mutar los valores almacenados .
Shelby Moore III
HTML no es un lenguaje de programación
lud
5
Desde que escribí mi respuesta anterior, he formulado una nueva definición de la propiedad declarativa que se cita a continuación. También he definido la programación imperativa como la propiedad dual.
Esta definición es superior a la que proporcioné en mi respuesta anterior, porque es sucinta y es más general. Pero puede ser más difícil de asimilar, porque la implicación de los teoremas de incompletitud aplicables a la programación y la vida en general son difíciles de entender para los humanos.
La explicación citada de la definición discute el papel que juega la programación funcional pura en la programación declarativa.
Declarativo versus imperativo
La propiedad declarativa es extraña, obtusa y difícil de capturar en una definición técnicamente precisa que sigue siendo general y no ambigua, porque es una noción ingenua de que podemos declarar el significado (también conocido como semántica) del programa sin incurrir en efectos secundarios no deseados. Existe una tensión inherente entre la expresión del significado y la evitación de efectos no deseados, y esta tensión en realidad deriva de los teoremas de incompletitud de la programación y nuestro universo.
Es una simplificación excesiva, técnicamente imprecisa y, a menudo, ambigua definir declarativo como " qué hacer " e imperativo como " cómo hacerlo " . Un caso ambiguo es el " qué " es el " cómo " en un programa que genera un programa: un compilador.
Evidentemente, la recursión ilimitada que hace que un lenguaje Turing sea completo , también está análogamente en la semántica, no solo en la estructura sintáctica de la evaluación (también conocida como semántica operativa). Esto es lógicamente un ejemplo análogo al teorema de Gödel: " cualquier sistema completo de axiomas también es inconsistente ". ¡Reflexione sobre la rareza contradictoria de esa cita! También es un ejemplo que demuestra cómo la expresión de la semántica no tiene demostrable obligado, por tanto, no podemos probar 2 que un programa (y análogamente su semántica) detuvo también conocido como el teorema de Detención.
Los teoremas de incompletitud derivan de la naturaleza fundamental de nuestro universo, que como se establece en la Segunda Ley de la Termodinámica es " la entropía (también conocida como el # de posibilidades independientes) está tendiendo al máximo para siempre ". La codificación y el diseño de un programa nunca terminan, ¡está vivo! Porque intenta abordar una necesidad del mundo real, y la semántica del mundo real siempre está cambiando y tiende a más posibilidades. Los humanos nunca dejan de descubrir cosas nuevas (incluidos errores en los programas ;-).
Para capturar de manera precisa y técnica esta noción deseada antes mencionada dentro de este universo extraño que no tiene borde (¡piense que no hay "fuera" de nuestro universo), requiere una definición concisa pero engañosamente no simple que sonará incorrecta hasta que se explique profundamente.
Definición:
La propiedad declarativa es donde puede existir un solo conjunto posible de declaraciones que pueden expresar cada semántica modular específica.
La propiedad imperativa 3 es la dual, donde la semántica es inconsistente en la composición y / o puede expresarse con variaciones de conjuntos de enunciados.
Esta definición de declarativa es distintivamente local en el ámbito semántico, lo que significa que requiere que una semántica modular mantenga su significado coherente independientemente de dónde y cómo se instancia y emplea en el ámbito global . Por lo tanto, cada semántica modular declarativa debería ser intrínsecamente ortogonal a todas las demás posibles, y no un algoritmo o modelo global imposible (debido a teoremas de incompletitud) para presenciar la coherencia, que también es el punto de " Más no siempre es mejor " por Robert Harper, profesor de Informática en la Universidad Carnegie Mellon, uno de los diseñadores de Standard ML.
Ejemplos de estos incluyen semántica declarativa modulares categoría funtores teoría, por ejemplo, laApplicative , mecanografía nominal, espacios de nombres, los campos de nombre y WRT a nivel operativo de la semántica a continuación, la programación funcional pura.
Por lo tanto, los lenguajes declarativos bien diseñados pueden expresar más claramente el significado , aunque con cierta pérdida de generalidad en lo que se puede expresar, pero una ganancia en lo que se puede expresar con consistencia intrínseca.
Un ejemplo de la definición antes mencionada es el conjunto de fórmulas en las celdas de un programa de hoja de cálculo, que no se espera que den el mismo significado cuando se mueven a diferentes celdas de columna y fila, es decir, los identificadores de celda cambiaron. Los identificadores de celda son parte y no son superfluos para el significado pretendido. Por lo tanto, el resultado de cada hoja de cálculo es wrt único para los identificadores de celda en un conjunto de fórmulas. La semántica modular consistente en este caso es el uso de identificadores de celda como entrada y salida de funciones puras para fórmulas de celdas (ver más abajo).
Hyper Text Markup Language, también conocido como HTML, el lenguaje para páginas web estáticas, es un ejemplo de un lenguaje declarativo altamente (pero no perfectamente 3 ) que (al menos antes de HTML 5) no tenía capacidad para expresar un comportamiento dinámico. HTML es quizás el lenguaje más fácil de aprender. Para el comportamiento dinámico, un lenguaje de script imperativo como JavaScript generalmente se combinaba con HTML. HTML sin JavaScript se ajusta a la definición declarativa porque cada tipo nominal (es decir, las etiquetas) mantiene su significado consistente en la composición dentro de las reglas de la sintaxis.
Una definición competitiva para declarativa son las propiedades conmutativas e idempotentes de las declaraciones semánticas, es decir, que las declaraciones pueden reordenarse y duplicarse sin cambiar el significado. Por ejemplo, las declaraciones que asignan valores a campos con nombre pueden reordenarse y duplicarse sin cambiar el significado del programa, si esos nombres son modulares en cualquier orden implícito. Los nombres a veces implican un orden, por ejemplo, los identificadores de celda incluyen su posición de columna y fila; mover un total en la hoja de cálculo cambia su significado. De lo contrario, estas propiedades requieren implícitamente globalConsistencia de la semántica. En general, es imposible diseñar la semántica de las declaraciones para que permanezcan consistentes si se ordenan o duplican al azar, porque el orden y la duplicación son intrínsecos a la semántica. Por ejemplo, las declaraciones "Foo existe" (o construcción) y "Foo no existe" (y destrucción). Si uno considera que la inconsistencia aleatoria es endémica de la semántica prevista, entonces acepta esta definición como lo suficientemente general para la propiedad declarativa. En esencia, esta definición es vacía como una definición generalizada porque intenta hacer que la consistencia sea ortogonal a la semántica, es decir, desafiar el hecho de que el universo de la semántica es dinámicamente ilimitado y no puede ser capturado en un paradigma de coherencia global .
Requerir las propiedades conmutativas e idempotentes para la (orden de evaluación estructural de) la semántica operacional de nivel inferior convierte la semántica operacional en una semántica modular declarativa localizada , por ejemplo, programación funcional pura (incluyendo recursión en lugar de bucles imperativos). Luego, el orden operativo de los detalles de implementación no impacta (es decir, se extiende globalmente en) la consistencia de la semántica de nivel superior. Por ejemplo, el orden de evaluación de (y teóricamente también la duplicación de) las fórmulas de la hoja de cálculo no importa porque las salidas no se copian a las entradas hasta después de que todas las salidas se hayan calculado, es decir, de forma análoga a las funciones puras.
C, Java, C ++, C #, PHP y JavaScript no son particularmente declarativos. La sintaxis de Copute y la sintaxis de Python se asocian más declarativamente a los resultados esperados , es decir, una semántica sintáctica consistente que elimina lo extraño para que uno pueda comprender fácilmente el código después de haberlo olvidado. Copute y Haskell imponen el determinismo de la semántica operativa y alientan " no te repitas " (DRY), porque solo permiten el paradigma funcional puro.
2 Incluso cuando podemos probar la semántica de un programa, por ejemplo, con el lenguaje Coq, esto se limita a la semántica que se expresa en la tipificación , y la tipificación nunca puede capturar toda la semántica de un programa, ni siquiera para los idiomas que son No está completo, por ejemplo, con HTML + CSS es posible expresar combinaciones inconsistentes que tienen una semántica indefinida.
3 Muchas explicaciones afirman incorrectamente que solo la programación imperativa tiene sentencias ordenadas sintácticamente. Aclaré esta confusión entre la programación imperativa y funcional . Por ejemplo, el orden de las declaraciones HTML no reduce la coherencia de su significado.
en programación funcional ... el rango de variación de una variable es un tipo
Dependiendo de cómo se distinga la programación funcional de la imperativa, su 'asignable' en un programa imperativo también puede tener un tipo que pone un límite a su variabilidad.
La única definición no confusa que aprecio actualmente para la programación funcional es a) funciones como objetos y tipos de primera clase, b) preferencia por la recursión sobre bucles, y / o c) funciones puras, es decir, aquellas funciones que no afectan la semántica deseada del programa cuando se memoriza (por lo tanto, la programación funcional perfectamente pura no existe en una semántica denotativa de propósito general debido a los impactos de la semántica operativa, por ejemplo, la asignación de memoria ).
La propiedad idempotente de una función pura significa que la llamada a la función en sus variables puede ser sustituida por su valor, que generalmente no es el caso para los argumentos de un procedimiento imperativo. Las funciones puras parecen ser wrt declarativas para las transiciones de estado no compuestas entre los tipos de entrada y resultado.
Pero la composición de las funciones puras no mantiene tal consistencia, porque es posible modelar un proceso imperativo de efectos secundarios (estado global) en un lenguaje de programación funcional puro, por ejemplo, IOMonad de Haskell y, además, es completamente imposible evitar hacerlo. cualquier lenguaje de programación funcional puro completo de Turing.
Como escribí en 2012, que parece un consenso similar de comentarios en su blog reciente , esa programación declarativa es un intento de capturar la noción de que la semántica prevista nunca es opaca. Ejemplos de semántica opaca son la dependencia del orden, la dependencia del borrado de la semántica de nivel superior en la capa de semántica operativa (por ejemplo, los modelos no son conversiones y los genéricos reificados limitan la semántica de nivel superior ) y la dependencia de valores variables que no pueden verificarse (demostrarse correcto) por el lenguaje de programación.
Por lo tanto, he concluido que solo los idiomas completos que no son de Turing pueden ser declarativos.
Por lo tanto, un atributo inequívoco y distinto de un lenguaje declarativo podría ser que se puede demostrar que su salida obedece a un conjunto enumerable de reglas generativas. Por ejemplo, para cualquier programa HTML específico (ignorando las diferencias en las formas en que los intérpretes divergen) que no está programado (es decir, no está completo en Turing), entonces su variabilidad de salida puede ser enumerable. O más sucintamente, un programa HTML es una función pura de su variabilidad. Lo mismo ocurre con un programa de hoja de cálculo es una función pura de sus variables de entrada.
Por lo tanto, me parece que los lenguajes declarativos son la antítesis de la
recursión ilimitada , es decir, según el segundo teorema de incompletitud de Gödel, los teoremas autorreferenciales no se pueden probar.
Lesie Lamport escribió un cuento de hadas sobre cómo Euclides podría haber trabajado en torno a los teoremas de incompletitud de Gödel aplicados a las pruebas matemáticas en el contexto del lenguaje de programación por congruencia entre tipos y lógica (correspondencia de Curry-Howard, etc.).
La programación declarativa es "el acto de programar en lenguajes que se ajustan al modelo mental del desarrollador en lugar del modelo operativo de la máquina".
La diferencia entre programación declarativa e imperativa está bien ilustrada por el problema de analizar datos estructurados.
Un programa imperativo usaría funciones recursivas para consumir datos y generar datos. Un programa declarativo expresaría una gramática que define la estructura de los datos para que luego puedan analizarse.
La diferencia entre estos dos enfoques es que el programa declarativo crea un nuevo lenguaje que está más relacionado con el modelo mental del problema que su lenguaje anfitrión.
Puede sonar extraño, pero agregaría Excel (o cualquier hoja de cálculo realmente) a la lista de sistemas declarativos. Un buen ejemplo de esto se da aquí .
Por lo que puedo decir, comenzó a usarse para describir sistemas de programación como Prolog, porque prolog se trata (supuestamente) de declarar cosas de una manera abstracta.
Cada vez significa menos, ya que tiene la definición dada por los usuarios anteriores. Debe quedar claro que existe un abismo entre la programación declarativa de Haskell y la programación declarativa de HTML.
No existe un "abismo entre la programación declarativa de Haskell y la programación declarativa de HTML", porque el atributo raíz de la programación declarativa es la inmutabilidad de los valores almacenados.
Shelby Moore III
Sea como fuere, hay una gran diferencia entre un lenguaje específico de dominio que está limitado incluso en sus cálculos implícitos, en comparación con un sistema de programación completo.
Marcin
Convenido. La integridad de Turing es ortogonal a la inmutabilidad de los valores almacenados. Por lo tanto, no debemos combinar con el atributo declarativo versus imperativo. Gracias por pensar en uno de los atributos (integridad de Turing) que puede causar ese "abismo".
Un par de otros ejemplos de programación declarativa:
Marcado ASP.Net para enlace de datos. Simplemente dice "llene esta cuadrícula con esta fuente", por ejemplo, y deja en manos del sistema cómo sucede eso.
Expresiones linq
La programación declarativa es buena porque puede ayudar a simplificar su modelo mental * de código, y porque eventualmente podría ser más escalable.
Por ejemplo, supongamos que tiene una función que hace algo a cada elemento en una matriz o lista. El código tradicional se vería así:
foreach (object item in MyList)
{
DoSomething(item);
}
No es gran cosa allí. Pero, ¿qué sucede si usa la sintaxis más declarativa y en su lugar define DoSomething () como una Acción? Entonces puedes decirlo de esta manera:
MyList.ForEach(DoSometing);
Esto es, por supuesto, más conciso. Pero estoy seguro de que tiene más preocupaciones que solo guardar dos líneas de código aquí y allá. Rendimiento, por ejemplo. A la antigua usanza, el procesamiento debía hacerse en secuencia. ¿Qué pasaría si el método .ForEach () tuviera una forma de indicar que podría manejar el procesamiento en paralelo, automáticamente? Ahora, de repente, ha hecho su código multiproceso de una manera muy segura y solo ha cambiado una línea de código. Y, de hecho, hay una extensión para .Net que te permite hacer exactamente eso.
Si sigues ese enlace, te lleva a una publicación de blog de un amigo mío. Toda la publicación es un poco larga, pero puede desplazarse hacia abajo hasta el encabezado titulado "El problema" _ y retomarla sin ningún problema. *
La programación declarativa puede mutar los valores almacenados ... es solo que usted especifica (declara) lo que quiere mutar en lugar de exactamente cómo hacerlo. ¿Qué más crees que hace una instrucción sql INSERT o UPDATE en sql?
Joel Coehoorn
Te estás perdiendo el punto de que si tus funciones no son puras, los efectos secundarios no deseados pueden destruir la relación entre lo que declaraste y el comportamiento real del programa. Lo expliqué con más detalle en una nueva respuesta .
Shelby Moore III
-3
Depende de cómo envíe la respuesta al texto. En general, puede mirar el programa desde una determinada vista, pero depende del ángulo en que mire el problema. Comenzaré con el programa: Dim Bus, Auto, Time, Height As Integr
Nuevamente, depende de cuál sea el problema en general. Puede que tenga que acortarlo debido al programa. Espero que esto ayude y necesito los comentarios si no es así. Gracias.
Respuestas:
La programación declarativa es cuando escribes tu código de tal manera que describe lo que quieres hacer, y no cómo quieres hacerlo. Le corresponde al compilador averiguar el cómo.
Ejemplos de lenguajes de programación declarativos son SQL y Prolog.
fuente
Las otras respuestas ya hacen un trabajo fantástico al explicar qué es la programación declarativa, así que solo voy a proporcionar algunos ejemplos de por qué eso podría ser útil.
Independencia de contexto
Los programas declarativos son independientes del contexto . Debido a que solo declaran cuál es el objetivo final, pero no los pasos intermedios para alcanzar ese objetivo, se puede usar el mismo programa en diferentes contextos. Esto es difícil de hacer con los programas imperativos , porque a menudo dependen del contexto (por ejemplo, estado oculto).
Toma
yacc
como ejemplo. Es un generador de analizador alias. compilador compilador, un DSL declarativo externo para describir la gramática de un idioma, de modo que se pueda generar automáticamente un analizador para ese idioma a partir de la descripción. Debido a su independencia de contexto, puede hacer muchas cosas diferentes con dicha gramática:yacc
)Y muchos más …
Mejoramiento
Debido a que no prescribe a la computadora qué pasos tomar y en qué orden, puede reorganizar su programa mucho más libremente, incluso puede ejecutar algunas tareas en paralelo. Un buen ejemplo es un planificador de consultas y un optimizador de consultas para una base de datos SQL. La mayoría de las bases de datos SQL le permiten mostrar la consulta que realmente están ejecutando frente a la consulta que les pidió que ejecutaran. A menudo, esas consultas no parecen nadacomo el uno al otro. El planificador de consultas tiene en cuenta cosas que ni siquiera hubiera soñado: la latencia rotacional del disco, por ejemplo, o el hecho de que una aplicación completamente diferente para un usuario completamente diferente acaba de ejecutar una consulta similar y la tabla que usted es unirse y trabajar tan duro para evitar cargar ya está en la memoria de todos modos.
No es una disyuntiva interesante aquí: la máquina tiene que trabajar más para averiguar cómo hacer algo de lo que sería en un lenguaje imperativo, pero cuando se hace entenderlo, tiene mucha más libertad y mucha más información para la optimización etapa.
fuente
Flojamente:
La programación declarativa tiende a: -
La programación imperativa tiende a: -
Como resultado, un estilo imperativo ayuda al lector a comprender la mecánica de lo que realmente está haciendo el sistema, pero puede dar poca información sobre el problema que se pretende resolver. Por otro lado, un estilo declarativo ayuda al lector a comprender el dominio del problema y el enfoque que el sistema adopta para la solución del problema, pero es menos informativo sobre el tema de la mecánica.
Los programas reales (incluso los escritos en lenguajes que favorecen los extremos del espectro, como ProLog o C) tienden a tener ambos estilos presentes en varios grados en varios puntos, para satisfacer las diversas complejidades y necesidades de comunicación de la pieza. Un estilo no es superior al otro; solo sirven para diferentes propósitos y, como con muchas cosas en la vida, la moderación es la clave.
fuente
Aquí hay un ejemplo.
En CSS (usado para diseñar páginas HTML), si desea que un elemento de imagen tenga 100 píxeles de alto y 100 píxeles de ancho, simplemente "declara" que eso es lo que quiere de la siguiente manera:
Puede considerar CSS un lenguaje declarativo de "hoja de estilo".
El motor del navegador que lee e interpreta este CSS es libre de hacer que la imagen parezca tan alta y ancha como quiera. Diferentes motores de navegador (por ejemplo, el motor para IE, el motor para Chrome) implementarán esta tarea de manera diferente.
Sus implementaciones únicas, por supuesto, NO están escritas en un lenguaje declarativo, sino en un lenguaje de procedimiento como Assembly, C, C ++, Java, JavaScript o Python. Ese código es un conjunto de pasos que se llevarán a cabo paso a paso (y puede incluir llamadas a funciones). Podría hacer cosas como interpolar valores de píxeles y renderizar en la pantalla.
fuente
Lo siento, pero debo estar en desacuerdo con muchas de las otras respuestas. Me gustaría detener este malentendido confuso de la definición de programación declarativa.
Definición
La transparencia referencial (RT) de las subexpresiones es el único atributo requerido de una expresión de programación declarativa , porque es el único atributo que no se comparte con la programación imperativa.
Otros atributos citados de programación declarativa, derivan de este RT. Haga clic en el hipervínculo de arriba para obtener una explicación detallada.
Ejemplo de hoja de cálculo
Dos respuestas mencionaron la programación de hojas de cálculo. En los casos en que la programación de la hoja de cálculo (también conocida como fórmulas) no accede al estado global mutable , entonces es la programación declarativa. Esto se debe a que los valores de celda mutables son la entrada y salida monolítica del
main()
(todo el programa). Los nuevos valores no se escriben en las celdas después de ejecutar cada fórmula, por lo que no son mutables durante la vida del programa declarativo (ejecución de todas las fórmulas en la hoja de cálculo). Por lo tanto, uno con respecto al otro, las fórmulas ven estas células mutables como inmutables. Se permite que una función RT acceda al estado global inmutable (y también al estado local mutable ).Por lo tanto, la capacidad de mutar los valores en las celdas cuando el programa termina (como resultado de
main()
) no los convierte en valores almacenados mutables en el contexto de las reglas. La distinción clave es que los valores de las celdas no se actualizan después de realizar cada fórmula de hoja de cálculo, por lo tanto, el orden de ejecución de las fórmulas no importa. Los valores de las celdas se actualizan después de que se hayan realizado todas las fórmulas declarativas.fuente
La programación declarativa es la imagen, donde la programación imperativa son instrucciones para pintar esa imagen.
Estás escribiendo en un estilo declarativo si estás "diciéndole lo que es", en lugar de describir los pasos que la computadora debe seguir para llegar a donde quieres.
Cuando usas XML para marcar datos, estás usando programación declarativa porque estás diciendo "Esta es una persona, es un cumpleaños y allí hay una dirección".
Algunos ejemplos de donde la programación declarativa e imperativa se combinan para un mayor efecto:
Windows Presentation Foundation utiliza la sintaxis XML declarativa para describir el aspecto de una interfaz de usuario y las relaciones (enlaces) entre los controles y las estructuras de datos subyacentes.
Los archivos de configuración estructurados usan sintaxis declarativa (tan simple como pares "clave = valor") para identificar lo que significa una cadena o valor de datos.
HTML marca el texto con etiquetas que describen qué papel tiene cada parte del texto en relación con todo el documento.
fuente
La programación declarativa es la programación con declaraciones, es decir, oraciones declarativas. Las oraciones declarativas tienen una serie de propiedades que las distinguen de las oraciones imperativas. En particular, las declaraciones son:
Un punto relevante es que estas son todas propiedades estructurales y son ortogonales al tema. Declarativo no se trata de "Qué vs. Cómo" . Podemos declarar (representar y restringir) un "cómo" tan fácilmente como declaramos un "qué" .Declarativo se trata de estructura, no de contenido. La programación declarativa tiene un impacto significativo en cómo abstraemos y refactorizamos nuestro código, y cómo lo modularizamos en subprogramas, pero no tanto en el modelo de dominio.
A menudo, podemos convertir de imperativo a declarativo agregando contexto. Por ejemplo, "Gire a la izquierda. (... espere ...) Gire a la derecha". a "Bob girará a la izquierda en la intersección de Foo y Bar a las 11:01. Bob girará a la derecha en la intersección de Bar y Baz a las 11:06". Tenga en cuenta que en el último caso las oraciones son idempotentes y conmutativas, mientras que en el primer caso reorganizar o repetir las oraciones cambiaría severamente el significado del programa.
Con respecto a lo monótono , las declaraciones pueden agregar restricciones que restan posibilidades . Pero las restricciones aún agregan información (más precisamente, las restricciones son información). Si necesitamos declaraciones que varíen en el tiempo, es típico modelar esto con una semántica temporal explícita, por ejemplo, desde "la pelota es plana" hasta "la pelota es plana en el momento T". Si tenemos dos declaraciones contradictorias, tenemos un sistema declarativo inconsistente, aunque esto podría resolverse introduciendo restricciones blandas (prioridades, probabilidades, etc.) o aprovechando una lógica paraconsistente.
fuente
Describiendo a una computadora lo que quieres, no cómo hacer algo.
fuente
imagina una página de Excel. Con columnas pobladas con fórmulas para calcular su declaración de impuestos.
Toda la lógica se hace declarada en las celdas, el orden del cálculo se determina mediante la fórmula misma en lugar de por procedimiento.
De eso se trata la programación declarativa. Usted declara el espacio del problema y la solución en lugar del flujo del programa.
Prolog es el único lenguaje declarativo que uso. Requiere un tipo diferente de pensamiento, pero es bueno aprender si solo para exponerlo a algo que no sea el típico lenguaje de programación procesal.
fuente
He refinado mi comprensión de la programación declarativa, desde diciembre de 2011, cuando proporcioné una respuesta a esta pregunta. Aquí sigue mi comprensión actual.
La versión larga de mi comprensión (investigación) se detalla en este enlace. , que debe leer para obtener una comprensión profunda del resumen que proporcionaré a continuación.
La programación imperativa es donde se almacena y lee el estado mutable, por lo que el orden y / o la duplicación de las instrucciones del programa pueden alterar el comportamiento (semántica) del programa (e incluso causar un error, es decir, un comportamiento involuntario).
En el sentido más ingenuo y extremo (que afirmé en mi respuesta anterior), la programación declarativa (DP) está evitando todo el estado mutable almacenado, por lo tanto, ordenar y / o duplicar las instrucciones del programa NO puede alterar el comportamiento (semántica) del programa .
Sin embargo, una definición tan extrema no sería muy útil en el mundo real, ya que casi todos los programas implican un estado mutable almacenado. El ejemplo de hoja de cálculo se ajusta a esta definición extrema de DP, porque todo el código del programa se ejecuta hasta su finalización con una copia estática del estado de entrada, antes de que se almacenen los nuevos estados. Luego, si se cambia algún estado, esto se repite. Pero la mayoría de los programas del mundo real no pueden limitarse a un modelo tan monolítico de cambios de estado.
Una definición más útil de DP es que el orden y / o la duplicación de las instrucciones de programación no alteran ninguna semántica opaca. En otras palabras, no se producen cambios aleatorios ocultos en la semántica; cualquier cambio en el orden y / o duplicación de las instrucciones del programa solo causa cambios intencionados y transparentes en el comportamiento del programa.
El siguiente paso sería hablar sobre qué modelos de programación o paradigmas ayudan en DP, pero esa no es la cuestión aquí.
fuente
Functional programming
es una palabra de moda en estos días que es esencialmente un subconjunto de programación declarativa. LINQ en lenguaje C # es un elemento de programación funcional cuando el lenguaje en sí es imprescindible por naturaleza. Entonces, C # se convierte en una especie de híbrido según esa definición.Es un método de programación basado en describir lo que algo debe hacer o ser en lugar de describir cómo debería funcionar.
En otras palabras, no escribes algoritmos hechos de expresiones, solo diseñas cómo quieres que sean las cosas. Dos buenos ejemplos son HTML y WPF.
Este artículo de Wikipedia es una buena descripción general: http://en.wikipedia.org/wiki/Declarative_programming
fuente
Desde que escribí mi respuesta anterior, he formulado una nueva definición de la propiedad declarativa que se cita a continuación. También he definido la programación imperativa como la propiedad dual.
Esta definición es superior a la que proporcioné en mi respuesta anterior, porque es sucinta y es más general. Pero puede ser más difícil de asimilar, porque la implicación de los teoremas de incompletitud aplicables a la programación y la vida en general son difíciles de entender para los humanos.
La explicación citada de la definición discute el papel que juega la programación funcional pura en la programación declarativa.
Editar: publiqué el siguiente comentario en el blog de Robert Harper:
fuente
La programación declarativa es "el acto de programar en lenguajes que se ajustan al modelo mental del desarrollador en lugar del modelo operativo de la máquina".
La diferencia entre programación declarativa e imperativa está bien ilustrada por el problema de analizar datos estructurados.
Un programa imperativo usaría funciones recursivas para consumir datos y generar datos. Un programa declarativo expresaría una gramática que define la estructura de los datos para que luego puedan analizarse.
La diferencia entre estos dos enfoques es que el programa declarativo crea un nuevo lenguaje que está más relacionado con el modelo mental del problema que su lenguaje anfitrión.
fuente
Puede sonar extraño, pero agregaría Excel (o cualquier hoja de cálculo realmente) a la lista de sistemas declarativos. Un buen ejemplo de esto se da aquí .
fuente
Lo explicaría como DP es una forma de expresar
... y donde hay un motor de deducciones que generalmente funciona con un algoritmo de unificación para encontrar los objetivos.
fuente
Por lo que puedo decir, comenzó a usarse para describir sistemas de programación como Prolog, porque prolog se trata (supuestamente) de declarar cosas de una manera abstracta.
Cada vez significa menos, ya que tiene la definición dada por los usuarios anteriores. Debe quedar claro que existe un abismo entre la programación declarativa de Haskell y la programación declarativa de HTML.
fuente
Un par de otros ejemplos de programación declarativa:
La programación declarativa es buena porque puede ayudar a simplificar su modelo mental * de código, y porque eventualmente podría ser más escalable.
Por ejemplo, supongamos que tiene una función que hace algo a cada elemento en una matriz o lista. El código tradicional se vería así:
No es gran cosa allí. Pero, ¿qué sucede si usa la sintaxis más declarativa y en su lugar define DoSomething () como una Acción? Entonces puedes decirlo de esta manera:
Esto es, por supuesto, más conciso. Pero estoy seguro de que tiene más preocupaciones que solo guardar dos líneas de código aquí y allá. Rendimiento, por ejemplo. A la antigua usanza, el procesamiento debía hacerse en secuencia. ¿Qué pasaría si el método .ForEach () tuviera una forma de indicar que podría manejar el procesamiento en paralelo, automáticamente? Ahora, de repente, ha hecho su código multiproceso de una manera muy segura y solo ha cambiado una línea de código. Y, de hecho, hay una extensión para .Net que te permite hacer exactamente eso.
fuente
Depende de cómo envíe la respuesta al texto. En general, puede mirar el programa desde una determinada vista, pero depende del ángulo en que mire el problema. Comenzaré con el programa: Dim Bus, Auto, Time, Height As Integr
Nuevamente, depende de cuál sea el problema en general. Puede que tenga que acortarlo debido al programa. Espero que esto ayude y necesito los comentarios si no es así. Gracias.
fuente