Programación declarativa

Paradigma de programación basado en el modelado de la lógica de un cómputo.

En informática , la programación declarativa es un paradigma de programación (un estilo de construir la estructura y los elementos de los programas informáticos) que expresa la lógica de un cálculo sin describir su flujo de control . [1]

Muchos lenguajes que aplican este estilo intentan minimizar o eliminar los efectos secundarios al describir lo que el programa debe lograr en términos del dominio del problema , en lugar de describir cómo lograrlo como una secuencia de primitivas del lenguaje de programación [2] (el cómo se deja en manos de la implementación del lenguaje ). Esto contrasta con la programación imperativa , que implementa algoritmos en pasos explícitos. [3] [4]

La programación declarativa suele considerar los programas como teorías de una lógica formal y los cálculos como deducciones en ese espacio lógico. La programación declarativa puede simplificar enormemente la escritura de programas paralelos . [5]

Los lenguajes declarativos comunes incluyen los lenguajes de consulta de bases de datos (por ejemplo, SQL , XQuery ), expresiones regulares , programación lógica (por ejemplo, Prolog , Datalog , programación de conjuntos de respuestas ), programación funcional , gestión de configuración y sistemas de modelado algebraico .

Definición

La programación declarativa suele definirse como cualquier estilo de programación que no sea imperativo. Otras definiciones comunes intentan definirla simplemente contrastándola con la programación imperativa. Por ejemplo:

Estas definiciones se superponen sustancialmente.

La programación declarativa es un estilo de programación no imperativo en el que los programas describen los resultados deseados sin enumerar explícitamente los comandos o pasos que deben realizarse. Los lenguajes de programación funcional y lógica se caracterizan por un estilo de programación declarativa. En la programación lógica, los programas consisten en oraciones expresadas en forma lógica, y los cálculos utilizan esas oraciones para resolver problemas, que también se expresan en forma lógica.

En un lenguaje funcional puro , como Haskell , todas las funciones no tienen efectos secundarios y los cambios de estado solo se representan como funciones que transforman el estado, que se representa explícitamente como un objeto de primera clase en el programa. Aunque los lenguajes funcionales puros no son imperativos, a menudo proporcionan una función para describir el efecto de una función como una serie de pasos. Otros lenguajes funcionales, como Lisp , OCaml y Erlang , admiten una mezcla de programación funcional y procedimental.

Algunos lenguajes de programación lógica, como Prolog , y lenguajes de consulta de bases de datos, como SQL, aunque declarativos en principio, también admiten un estilo de programación procedimental.

Subparadigmas

La programación declarativa es un término general que incluye varios paradigmas de programación más conocidos .

Programación de restricciones

La programación con restricciones establece relaciones entre variables en forma de restricciones que especifican las propiedades de la solución de destino. El conjunto de restricciones se resuelve asignando un valor a cada variable de modo que la solución sea coherente con el número máximo de restricciones. La programación con restricciones suele complementar otros paradigmas: programación funcional, lógica o incluso imperativa.

Lenguajes específicos de dominio

Entre los ejemplos más conocidos de lenguajes declarativos específicos de dominio (DSL) se incluyen el lenguaje de entrada del generador de analizador sintáctico yacc , QML , el lenguaje de especificación de compilación Make , el lenguaje de gestión de configuración de Puppet , expresiones regulares , Datalog , programación de conjuntos de respuestas y un subconjunto de SQL (consultas SELECT, por ejemplo). Los DSL tienen la ventaja de ser útiles sin tener que ser necesariamente Turing-completos , lo que hace que sea más fácil que un lenguaje sea puramente declarativo.

Muchos lenguajes de marcado como HTML , MXML , XAML , XSLT u otros lenguajes de marcado de interfaz de usuario suelen ser declarativos. HTML, por ejemplo, solo describe lo que debería aparecer en una página web; no especifica ni el flujo de control para representar una página ni las posibles interacciones de la página con un usuario .

A partir de 2013 [update], algunos sistemas de software [ ¿cuáles? ] combinan lenguajes de marcado de interfaz de usuario tradicionales (como HTML) con un marcado declarativo que define qué (pero no cómo) deben hacer los sistemas de servidor back-end para admitir la interfaz declarada. Dichos sistemas, que normalmente utilizan un espacio de nombres XML específico del dominio , pueden incluir abstracciones de sintaxis de base de datos SQL o llamadas parametrizadas a servicios web mediante transferencia de estado representacional (REST) ​​y SOAP . [ cita requerida ]

Programación funcional

Los lenguajes de programación funcional como Haskell , Scheme y ML evalúan expresiones a través de la aplicación de funciones. A diferencia del paradigma relacionado pero más imperativo de la programación procedimental , la programación funcional pone poco énfasis en la secuenciación explícita. En cambio, los cálculos se caracterizan por varios tipos de aplicación y composición de funciones recursivas de orden superior y, como tales, pueden considerarse simplemente como un conjunto de asignaciones entre dominios y codominios . Muchos lenguajes funcionales, incluidos la mayoría de los de las familias ML y Lisp, no son puramente funcionales y, por lo tanto, permiten la introducción de efectos con estado en los programas.

Lenguas híbridas

Los Makefiles, por ejemplo, especifican dependencias de forma declarativa, [7] pero también incluyen una lista imperativa de acciones a realizar. De manera similar, yacc especifica una gramática libre de contexto de forma declarativa, pero incluye fragmentos de código de un lenguaje anfitrión, que normalmente es imperativo (como C ).

Programación lógica

Los lenguajes de programación lógica, como Prolog , Datalog y la programación de conjuntos de respuestas , realizan los cálculos demostrando que un objetivo es una consecuencia lógica del programa o mostrando que el objetivo es verdadero en un modelo definido por el programa. Prolog realiza los cálculos reduciendo los objetivos a subobjetivos, de arriba hacia abajo mediante razonamiento inverso , mientras que la mayoría de los sistemas Datalog realizan los cálculos de abajo hacia arriba mediante razonamiento directo . Los programas de conjuntos de respuestas suelen utilizar solucionadores SAT para generar un modelo del programa.

Modelado

Los modelos, o representaciones matemáticas, de sistemas físicos pueden implementarse en código informático declarativo. El código contiene una serie de ecuaciones, no asignaciones imperativas, que describen ("declaran") las relaciones de comportamiento. Cuando un modelo se expresa en este formalismo, una computadora puede realizar manipulaciones algebraicas para formular mejor el algoritmo de solución. La causalidad matemática se impone típicamente en los límites del sistema físico, mientras que la descripción del comportamiento del sistema en sí es declarativa o acausal. Los lenguajes y entornos de modelado declarativos incluyen Analytica , Modelica y Simile. [8]

Ejemplos

Ceceo

Lisp es una familia de lenguajes de programación inspirados vagamente en la notación matemática y el cálculo lambda de Alonzo Church . Algunos dialectos, como Common Lisp , son principalmente imperativos pero admiten programación funcional. Otros, como Scheme , están diseñados para programación funcional.

En Scheme, la función factorial se puede definir de la siguiente manera:

( define ( factorial n ) ( si ( = n 0 ) 1 ;;; 0! = 1 ( * n ( factorial ( - n 1 ))))) ;;; n! = n*(n-1)!                

Esto define la función factorial mediante su definición recursiva. Por el contrario, es más habitual definir un procedimiento para un lenguaje imperativo.

En el cálculo lambda y en el lenguaje LISP, las funciones son, por lo general, ciudadanos de primera clase . En términos generales, esto significa que las funciones pueden ser entradas y salidas para otras funciones. Esto puede simplificar la definición de algunas funciones.

Por ejemplo, escribir una función para generar los primeros n números cuadrados en Racket se puede hacer de la siguiente manera:

( define ( first-n-squares n ) ( map ( lambda ( x ) ( * x x )) ;;; Una función que mapea x -> x^2 ( range n ))) ;;; Lista de los primeros n enteros no negativos            

La función de mapa acepta una función y una lista; la salida es una lista de resultados de la función de entrada en cada elemento de la lista de entrada.

Ml

ML (1973) [9] significa "Meta Lenguaje". ML está tipificado estáticamente y los argumentos de función y los tipos de retorno pueden ser anotados. [10]

diversión  veces_10 ( n  :  int )  :  int  =  10  *  n ;

ML no se centra tanto en los corchetes como Lisp y, en cambio, utiliza una variedad más amplia de sintaxis para codificar la relación entre los elementos del código, en lugar de recurrir al ordenamiento y la anidación de listas para expresar todo. La siguiente es una aplicación de times_10:

veces_10 2

Devuelve "20 : int", es decir, 20un valor de tipo int.

Al igual que Lisp , ML está diseñado para procesar listas, aunque todos los elementos de una lista deben ser del mismo tipo. [11]


Prólogo

Prolog (1972) significa "PROgramming in LOGic" (Programación en Lógica). Fue desarrollado para responder preguntas en lenguaje natural , [12] utilizando la resolución en lenguaje natural [13] tanto para deducir respuestas a consultas como para analizar y generar oraciones en lenguaje natural.

Los elementos básicos de un programa Prolog son hechos y reglas . A continuación se muestra un ejemplo sencillo:

gato ( tom ).  % tom es un gato ratón ( jerry ).  % jerry es un ratónanimal ( X )  :-  gato ( X ).  % cada gato es un animal animal ( X ) :  -  ratón ( X ).  % cada ratón es un animalgrande ( X )  :-  gato ( X ).  % cada gato es grande pequeño ( X )  :-  ratón ( X ).  % cada ratón es pequeñocomer ( X , Y )  :-  ratón ( X ),  queso ( Y ).  % cada ratón come cada queso comer ( X , Y )  :-  grande ( X ),  pequeño ( Y ).  % cada ser grande come cada ser pequeño

Dado este programa, la consulta tiene éxito, mientras que falla. Además, la consulta tiene éxito con la sustitución de respuesta .eat(tom,jerry)eat(jerry,tom)eat(X,jerry)X=tom

Prolog ejecuta programas de arriba hacia abajo, utilizando la resolución SLD para razonar hacia atrás , reduciendo los objetivos a subobjetivos. En este ejemplo, utiliza la última regla del programa para reducir el objetivo de responder la consulta a los subobjetivos de encontrar primero una X tal que se cumpla y luego demostrar que se cumple. Utiliza reglas repetidamente para reducir aún más los subobjetivos a otros subobjetivos, hasta que finalmente logra unificar todos los subobjetivos con hechos en el programa. Esta estrategia de razonamiento hacia atrás y reducción de objetivos trata las reglas en los programas lógicos como procedimientos y convierte a Prolog en un lenguaje de programación tanto declarativo como procedimental . [14]eat(X,jerry)big(X)small(jerry)

La amplia gama de aplicaciones de Prolog se destaca en el Libro del Año de Prolog, [15] que celebra el 50 aniversario de Prolog.

Registro de datos

Los orígenes de Datalog se remontan a los inicios de la programación lógica, pero se identificó como un área separada alrededor de 1977. Sintácticamente y semánticamente , es un subconjunto de Prolog. Pero debido a que no tiene términos compuestos , no es Turing-completo .

La mayoría de los sistemas Datalog ejecutan programas de abajo a arriba, utilizando reglas para razonar hacia adelante , derivando nuevos hechos a partir de hechos existentes y finalizando cuando no hay nuevos hechos que se puedan derivar, o cuando los hechos derivados se unifican con la consulta. En el ejemplo anterior, un sistema Datalog típico primero derivaría los nuevos hechos:

animal ( tom ). animal ( jerry ). grande ( tom ). pequeño ( jerry ).

Utilizando estos hechos, se derivaría el hecho adicional:

come ( tom ,  jerry ).

Entonces terminaría, tanto porque no se pueden derivar hechos nuevos adicionales, como porque el hecho recién derivado se unifica con la consulta.

come ( X ,  jerry ).

Datalog se ha aplicado a problemas como la integración de datos , la extracción de información , las redes , la seguridad , la computación en la nube y el aprendizaje automático . [16] [17]

Programación de conjuntos de respuestas

La programación de conjuntos de respuestas (ASP) evolucionó a fines de la década de 1990, basándose en la semántica del modelo estable (conjunto de respuestas) de la programación lógica. Al igual que Datalog, es un subconjunto de Prolog y, debido a que no tiene términos compuestos, no es Turing-completo.

La mayoría de las implementaciones de ASP ejecutan un programa primero "fundamentando" el programa, reemplazando todas las variables en las reglas por constantes de todas las formas posibles y luego utilizando un solucionador SAT proposicional, como el algoritmo DPLL para generar uno o más modelos del programa.

Sus aplicaciones están orientadas a resolver problemas difíciles de búsqueda y representación de conocimiento . [18] [19]

Véase también

Referencias

  1. ^ Lloyd, JW, Ventajas prácticas de la programación declarativa
  2. ^ "lenguaje declarativo". FOLDOC . 17 de mayo de 2004. Archivado desde el original el 7 de septiembre de 2023 . Consultado el 7 de septiembre de 2023 .
  3. ^ Sebesta, Robert (2016). Conceptos de lenguajes de programación . Boston: Pearson. ISBN 978-0-13-394302-3.OCLC 896687896  .
  4. ^ "Programación imperativa: visión general del paradigma de programación más antiguo". Guía digital de IONOS . 2021-05-21. Archivado desde el original el 2022-05-03 . Consultado el 2023-05-23 .
  5. ^ "DAMP 2009: Taller sobre aspectos declarativos de la programación multinúcleo". Cse.unsw.edu.au. 20 de enero de 2009. Archivado desde el original el 13 de septiembre de 2013. Consultado el 15 de agosto de 2013 .
  6. ^ Chakravarty, Manuel MT (14 de febrero de 1997). On the Massively Parallel Execution of Declarative Programs (Tesis doctoral). Technische Universität Berlin . Archivado desde el original el 23 de septiembre de 2015. Consultado el 26 de febrero de 2015. En este contexto, el criterio para llamar a un lenguaje de programación declarativo es la existencia de una correspondencia clara y matemáticamente establecida entre el lenguaje y la lógica matemática, de modo que una semántica declarativa para el lenguaje pueda basarse en el modelo o la teoría de la prueba (o ambos) de la lógica.
  7. ^ "Una visión general de los DSL". Archivado desde el original el 23 de octubre de 2007.
  8. ^ "Modelado declarativo". Simulistics. Archivado desde el original el 11 de agosto de 2003. Consultado el 15 de agosto de 2013 .
  9. ^ Gordon, Michael JC (1996). "De LCF a HOL: una breve historia". Archivado desde el original el 5 de septiembre de 2016. Consultado el 30 de octubre de 2021 .
  10. ^ Wilson, Leslie B. (2001). Lenguajes de programación comparativos, tercera edición . Addison-Wesley. pág. 233. ISBN 0-201-71012-9.
  11. ^ Wilson, Leslie B. (2001). Lenguajes de programación comparativos, tercera edición . Addison-Wesley. pág. 235. ISBN 0-201-71012-9.
  12. ^ "El nacimiento de Prolog" (PDF) . Noviembre de 1992. Archivado (PDF) desde el original el 2 de abril de 2015. Consultado el 25 de mayo de 2022 .
  13. ^ Robert Kowalski; Donald Kuehner (invierno de 1971). "Resolución lineal con función de selección" (PDF) . Inteligencia artificial . 2 (3–4): 227–260. doi :10.1016/0004-3702(71)90012-9. ISSN  0004-3702. Archivado (PDF) desde el original el 23 de septiembre de 2015 . Consultado el 13 de agosto de 2023 .
  14. ^ Robert Kowalski La lógica de predicados como lenguaje de programación Archivado el 7 de febrero de 2016 en Wayback Machine. Memo 70, Departamento de Inteligencia Artificial, Universidad de Edimburgo. 1973. También en Actas del Congreso IFIP, Estocolmo, North Holland Publishing Co., 1974, págs. 569-574.
  15. ^ Warren, DS (2023). "Introducción a Prolog". En Warren, DS; Dahl, V.; Eiter, T.; Hermenegildo, MV; Kowalski, R.; Rossi, F. (eds.). Prolog: los próximos 50 años . Notas de clase en informática(). Vol. 13900. Springer, Cham. págs. 3–19. doi :10.1007/978-3-031-35254-6_1. ISBN 978-3-031-35253-9.
  16. ^ Huang, Shan Shan; Green, Todd J.; Loo, Boon Thau (12-16 de junio de 2011). Datalog and Emerging applications (PDF) . SIGMOD 2011. Atenas, Grecia: Association for Computing Machinery. ISBN 978-1-4503-0661-4Archivado (PDF) del original el 22 de octubre de 2020. Consultado el 13 de agosto de 2023 .
  17. ^ Mei, Hongyuan; Qin, Guanghui; Xu, Minjie; Eisner, Jason (2020). "Registro de datos neuronal a través del tiempo: modelado temporal informado a través de la especificación lógica". Actas de ICML 2020 . arXiv : 2006.16723 .
  18. ^ Baral, Chitta (2003). Representación del conocimiento, razonamiento y resolución declarativa de problemas . Cambridge University Press. ISBN 978-0-521-81802-5.
  19. ^ Gelfond, Michael (2008). "Conjuntos de respuestas". En van Harmelen, Frank; Lifschitz, Vladimir; Porter, Bruce (eds.). Manual de representación del conocimiento . Elsevier. págs. 285–316. ISBN 978-0-08-055702-1.como PDF Archivado el 3 de marzo de 2016 en Wayback Machine.
  • Frans Coenen. Características de los lenguajes de programación declarativos. 1999.
  • Roberto Harper .
    • ¿Qué es, si es que hay algo, un lenguaje declarativo?. 2013.
    • "Existe un lenguaje declarativo y es el mejor DSL del mundo". 2013.
  • Olof Torgersson. Una nota sobre los paradigmas de programación declarativa y el futuro de la programación definicional. 1996.
Retrieved from "https://en.wikipedia.org/w/index.php?title=Declarative_programming&oldid=1245932781"