Programación funcional

Paradigma de programación basado en la aplicación y composición de funciones

En informática , la programación funcional es un paradigma de programación en el que los programas se construyen aplicando y componiendo funciones . Es un paradigma de programación declarativa en el que las definiciones de funciones son árboles de expresiones que asignan valores a otros valores, en lugar de una secuencia de declaraciones imperativas que actualizan el estado de ejecución del programa.

En la programación funcional, las funciones se consideran ciudadanos de primera clase , lo que significa que se pueden vincular a nombres (incluidos los identificadores locales ), pasar como argumentos y devolver desde otras funciones, al igual que cualquier otro tipo de datos . Esto permite escribir programas en un estilo declarativo y componible , donde las funciones pequeñas se combinan de manera modular .

La programación funcional a veces se considera sinónimo de programación puramente funcional , un subconjunto de la programación funcional que trata todas las funciones como funciones matemáticas deterministas o funciones puras . Cuando se llama a una función pura con algunos argumentos dados, siempre devolverá el mismo resultado y no puede verse afectada por ningún estado mutable u otros efectos secundarios . Esto contrasta con los procedimientos impuros , comunes en la programación imperativa , que pueden tener efectos secundarios (como modificar el estado del programa o tomar la entrada de un usuario). Los defensores de la programación puramente funcional afirman que al restringir los efectos secundarios, los programas pueden tener menos errores , ser más fáciles de depurar y probar , y ser más adecuados para la verificación formal . [1] [2]

La programación funcional tiene sus raíces en el ámbito académico , evolucionando a partir del cálculo lambda , un sistema formal de computación basado únicamente en funciones. La programación funcional ha sido históricamente menos popular que la programación imperativa, pero muchos lenguajes funcionales se utilizan hoy en día en la industria y la educación, incluidos Common Lisp , Scheme , [3] [4 ] [5] [6] Clojure , Wolfram Language , [7] [8] Racket , [9] Erlang , [10] [11] [12] Elixir , [13] OCaml , [14] [15] Haskell , [16] [17] y F# . [18] [19] Lean es un lenguaje de programación funcional que se utiliza comúnmente para verificar teoremas matemáticos. [20] La programación funcional también es clave para algunos lenguajes que han tenido éxito en dominios específicos, como JavaScript en la Web, [21] R en estadística, [22] [23] J , K y Q en análisis financiero y XQuery / XSLT para XML . [24] [25] Los lenguajes declarativos específicos de dominio como SQL y Lex / Yacc utilizan algunos elementos de la programación funcional, como no permitir valores mutables . [26] Además, muchos otros lenguajes de programación admiten la programación en un estilo funcional o han implementado características de la programación funcional, como C++11 , C# , [27] Kotlin , [28] Perl , [29] PHP , [30] Python , [31] Go , [32] Rust , [33] Raku , [34] Scala , [35] y Java (desde Java 8) . [36]

Debido a su componibilidad , los paradigmas de programación funcional pueden ser adecuados para arquitecturas basadas en microservicios . [37]

Historia

El cálculo lambda , desarrollado en la década de 1930 por Alonzo Church , es un sistema formal de computación construido a partir de la aplicación de funciones . En 1937, Alan Turing demostró que el cálculo lambda y las máquinas de Turing son modelos equivalentes de computación, [38] mostrando que el cálculo lambda es Turing completo . El cálculo lambda forma la base de todos los lenguajes de programación funcional. Una formulación teórica equivalente, la lógica combinatoria , fue desarrollada por Moses Schönfinkel y Haskell Curry en las décadas de 1920 y 1930. [39]

Posteriormente, Church desarrolló un sistema más débil, el cálculo lambda de tipos simples , que extendió el cálculo lambda asignando un tipo de datos a todos los términos. [40] Esto constituye la base de la programación funcional de tipos estáticos.

El primer lenguaje de programación funcional de alto nivel , Lisp , fue desarrollado a finales de los años 1950 para la serie de ordenadores científicos IBM 700/7000 por John McCarthy mientras estaba en el Instituto Tecnológico de Massachusetts (MIT). [41] Las funciones de Lisp se definieron utilizando la notación lambda de Church, extendida con una construcción de etiquetas para permitir funciones recursivas . [42] Lisp introdujo por primera vez muchas características paradigmáticas de la programación funcional, aunque los primeros Lisp eran lenguajes multiparadigma e incorporaron soporte para numerosos estilos de programación a medida que evolucionaban nuevos paradigmas. Los dialectos posteriores, como Scheme y Clojure , y derivaciones como Dylan y Julia , buscaron simplificar y racionalizar Lisp en torno a un núcleo funcional limpio, mientras que Common Lisp fue diseñado para preservar y actualizar las características paradigmáticas de los numerosos dialectos más antiguos que reemplazó. [43]

El lenguaje de procesamiento de información (IPL), de 1956, se cita a veces como el primer lenguaje de programación funcional basado en computadora. [44] Es un lenguaje de estilo ensamblador para manipular listas de símbolos. Tiene una noción de generador , que equivale a una función que acepta una función como argumento y, dado que es un lenguaje de nivel ensamblador, el código puede ser datos, por lo que se puede considerar que IPL tiene funciones de orden superior. Sin embargo, se basa en gran medida en la estructura de lista mutante y características imperativas similares.

Kenneth E. Iverson desarrolló APL a principios de la década de 1960, descrito en su libro de 1962 A Programming Language ( ISBN  9780471430148 ). APL fue la principal influencia en FP de John Backus . A principios de la década de 1990, Iverson y Roger Hui crearon J. A mediados de la década de 1990, Arthur Whitney , que había trabajado anteriormente con Iverson, creó K , que se utiliza comercialmente en las industrias financieras junto con su descendiente Q.

A mediados de la década de 1960, Peter Landin inventó la máquina SECD , [45] la primera máquina abstracta para un lenguaje de programación funcional, [46] describió una correspondencia entre ALGOL 60 y el cálculo lambda , [47] [48] y propuso el lenguaje de programación ISWIM . [49]

John Backus presentó la FP en su conferencia del Premio Turing de 1977 "¿Puede la programación liberarse del estilo von Neumann ? Un estilo funcional y su álgebra de programas". [50] Define los programas funcionales como construidos de manera jerárquica por medio de "formas de combinación" que permiten un "álgebra de programas"; en lenguaje moderno, esto significa que los programas funcionales siguen el principio de composicionalidad . [ cita requerida ] El artículo de Backus popularizó la investigación sobre programación funcional, aunque enfatizó la programación a nivel de función en lugar del estilo de cálculo lambda ahora asociado con la programación funcional.

El lenguaje ML de 1973 fue creado por Robin Milner en la Universidad de Edimburgo , y David Turner desarrolló el lenguaje SASL en la Universidad de St Andrews . También en Edimburgo en la década de 1970, Burstall y Darlington desarrollaron el lenguaje funcional NPL . [51] NPL se basó en las ecuaciones de recursión de Kleene y se introdujo por primera vez en su trabajo sobre la transformación de programas. [52] Burstall, MacQueen y Sannella luego incorporaron la verificación de tipos polimórficos de ML para producir el lenguaje Hope . [53] ML eventualmente se desarrolló en varios dialectos, los más comunes de los cuales ahora son OCaml y ML estándar .

En la década de 1970, Guy L. Steele y Gerald Jay Sussman desarrollaron Scheme , como se describe en los documentos Lambda y en el libro de texto Structure and Interpretation of Computer Programs de 1985. Scheme fue el primer dialecto de Lisp que utilizó el alcance léxico y requirió optimización de llamadas finales , características que fomentan la programación funcional.

En la década de 1980, Per Martin-Löf desarrolló la teoría de tipos intuicionista (también llamada teoría de tipos constructiva ), que asociaba programas funcionales con pruebas constructivas expresadas como tipos dependientes . Esto condujo a nuevos enfoques para la demostración interactiva de teoremas y ha influido en el desarrollo de lenguajes de programación funcional posteriores. [ cita requerida ]

El lenguaje funcional perezoso Miranda , desarrollado por David Turner, apareció inicialmente en 1985 y tuvo una fuerte influencia en Haskell . Como Miranda era un lenguaje propietario, Haskell comenzó a consensuar en 1987 la creación de un estándar abierto para la investigación en programación funcional; desde 1990 se han estado realizando lanzamientos de implementaciones.

Más recientemente, se ha encontrado uso en nichos como el CAD paramétrico en el lenguaje OpenSCAD construido sobre el marco CGAL , aunque su restricción en la reasignación de valores (todos los valores se tratan como constantes) ha generado confusión entre los usuarios que no están familiarizados con la programación funcional como concepto. [54]

La programación funcional continúa utilizándose en entornos comerciales. [55] [56] [57]

Conceptos

Una serie de conceptos [58] y paradigmas son específicos de la programación funcional y generalmente ajenos a la programación imperativa (incluida la programación orientada a objetos ). Sin embargo, los lenguajes de programación suelen atender a varios paradigmas de programación, por lo que los programadores que utilizan lenguajes "mayoritariamente imperativos" pueden haber utilizado algunos de estos conceptos. [59]

Funciones de primera clase y de orden superior

Las funciones de orden superior son funciones que pueden tomar otras funciones como argumentos o devolverlas como resultados. En cálculo, un ejemplo de función de orden superior es el operador diferencial , que devuelve la derivada de una función . d / d incógnita {\estilo de visualización d/dx} F {\estilo de visualización f}

Las funciones de orden superior están estrechamente relacionadas con las funciones de primera clase en el sentido de que tanto las funciones de orden superior como las de primera clase permiten que las funciones sean argumentos y resultados de otras funciones. La distinción entre ambas es sutil: "de orden superior" describe un concepto matemático de funciones que operan sobre otras funciones, mientras que "de primera clase" es un término informático para las entidades del lenguaje de programación que no tienen restricciones en su uso (por lo tanto, las funciones de primera clase pueden aparecer en cualquier parte del programa en la que otras entidades de primera clase, como los números, pueden hacerlo, incluso como argumentos de otras funciones y como sus valores de retorno).

Las funciones de orden superior permiten la aplicación parcial o currificación , una técnica que aplica una función a sus argumentos uno a la vez, y cada aplicación devuelve una nueva función que acepta el siguiente argumento. Esto permite que un programador exprese de manera sucinta, por ejemplo, la función sucesora como el operador de suma parcialmente aplicado al número natural uno.

Funciones puras

Las funciones (o expresiones) puras no tienen efectos secundarios (memoria o E/S). Esto significa que las funciones puras tienen varias propiedades útiles, muchas de las cuales se pueden utilizar para optimizar el código:

  • Si no se utiliza el resultado de una expresión pura, se puede eliminar sin afectar a otras expresiones.
  • Si se llama a una función pura con argumentos que no causan efectos secundarios, el resultado es constante con respecto a esa lista de argumentos (a veces llamado transparencia referencial o idempotencia ), es decir, llamar a la función pura nuevamente con los mismos argumentos devuelve el mismo resultado. (Esto puede habilitar optimizaciones de almacenamiento en caché como la memorización ).
  • Si no existe dependencia de datos entre dos expresiones puras, su orden se puede invertir o se pueden ejecutar en paralelo y no pueden interferir entre sí (en otros términos, la evaluación de cualquier expresión pura es segura para subprocesos ).
  • Si el lenguaje completo no permite efectos secundarios, entonces se puede utilizar cualquier estrategia de evaluación; esto le da al compilador la libertad de reordenar o combinar la evaluación de expresiones en un programa (por ejemplo, usando deforestación ).

Aunque la mayoría de los compiladores para lenguajes de programación imperativos detectan funciones puras y realizan la eliminación de subexpresiones comunes para llamadas a funciones puras, no siempre pueden hacer esto para bibliotecas precompiladas, que generalmente no exponen esta información, impidiendo así optimizaciones que involucran esas funciones externas. Algunos compiladores, como gcc , agregan palabras clave adicionales para que un programador marque explícitamente las funciones externas como puras, para habilitar tales optimizaciones. Fortran 95 también permite que las funciones se designen como puras . [60] C++11 agregó constexpruna palabra clave con semántica similar.

Recursión

La iteración (bucles) en lenguajes funcionales se logra generalmente mediante recursión . Las funciones recursivas se invocan a sí mismas, permitiendo que una operación se repita hasta que alcance el caso base . En general, la recursión requiere mantener una pila , que consume espacio en una cantidad lineal a la profundidad de la recursión. Esto podría hacer que la recursión sea prohibitivamente cara de usar en lugar de bucles imperativos. Sin embargo, un compilador puede reconocer y optimizar una forma especial de recursión conocida como recursión de cola en el mismo código utilizado para implementar la iteración en lenguajes imperativos. La optimización de la recursión de cola se puede implementar transformando el programa en un estilo de paso de continuación durante la compilación, entre otros enfoques.

El estándar del lenguaje Scheme requiere que las implementaciones admitan la recursión de cola adecuada, lo que significa que deben permitir un número ilimitado de llamadas de cola activas. [61] [62] La recursión de cola adecuada no es simplemente una optimización; es una característica del lenguaje que asegura a los usuarios que pueden usar la recursión para expresar un bucle y que hacerlo sería seguro para el espacio. [63] Además, al contrario de su nombre, tiene en cuenta todas las llamadas de cola, no solo la recursión de cola. Si bien la recursión de cola adecuada generalmente se implementa convirtiendo el código en bucles imperativos, las implementaciones pueden implementarla de otras maneras. Por ejemplo, Chicken mantiene intencionalmente una pila y deja que la pila se desborde . Sin embargo, cuando esto sucede, su recolector de basura reclamará espacio, [64] lo que permite un número ilimitado de llamadas de cola activas aunque no convierta la recursión de cola en un bucle.

Los patrones comunes de recursión se pueden abstraer utilizando funciones de orden superior, siendo los catamorfismos y anamorfismos (o "pliegues" y "despliegues") los ejemplos más obvios. Estos esquemas de recursión desempeñan un papel análogo al de las estructuras de control integradas, como los bucles en los lenguajes imperativos .

La mayoría de los lenguajes de programación funcional de propósito general permiten la recursión sin restricciones y son completos de Turing , lo que hace que el problema de detención sea indecidible , puede causar falta de solidez en el razonamiento ecuacional y generalmente requiere la introducción de inconsistencia en la lógica expresada por el sistema de tipos del lenguaje . Algunos lenguajes de propósito especial como Coq solo permiten la recursión bien fundada y son fuertemente normalizadores (los cálculos no terminantes solo se pueden expresar con flujos infinitos de valores llamados codatos ). Como consecuencia, estos lenguajes no son completos de Turing y expresar ciertas funciones en ellos es imposible, pero aún pueden expresar una amplia clase de cálculos interesantes al tiempo que evitan los problemas introducidos por la recursión sin restricciones. La programación funcional limitada a la recursión bien fundada con algunas otras restricciones se llama programación funcional total . [65]

Evaluación estricta versus no estricta

Los lenguajes funcionales se pueden clasificar según si utilizan evaluación estricta (ansiosa) o no estricta (perezosa) , conceptos que hacen referencia a cómo se procesan los argumentos de una función cuando se evalúa una expresión. La diferencia técnica está en la semántica denotacional de las expresiones que contienen cálculos fallidos o divergentes. En la evaluación estricta, la evaluación de cualquier término que contenga un subtérmino fallido falla. Por ejemplo, la expresión:

longitud de impresión ([2+1, 3*2, 1/0, 5-4])

falla en la evaluación estricta debido a la división por cero en el tercer elemento de la lista. En la evaluación perezosa, la función length devuelve el valor 4 (es decir, la cantidad de elementos en la lista), ya que al evaluarla no se intenta evaluar los términos que componen la lista. En resumen, la evaluación estricta siempre evalúa completamente los argumentos de la función antes de invocar la función. La evaluación perezosa no evalúa los argumentos de la función a menos que sus valores sean necesarios para evaluar la llamada a la función en sí.

La estrategia de implementación habitual para la evaluación perezosa en lenguajes funcionales es la reducción de grafos . [66] La evaluación perezosa se utiliza de forma predeterminada en varios lenguajes funcionales puros, incluidos Miranda , Clean y Haskell .

Hughes 1984 defiende la evaluación perezosa como un mecanismo para mejorar la modularidad del programa a través de la separación de preocupaciones , al facilitar la implementación independiente de productores y consumidores de flujos de datos. [2] Launchbury 1993 describe algunas dificultades que introduce la evaluación perezosa, particularmente al analizar los requisitos de almacenamiento de un programa, y ​​propone una semántica operacional para ayudar en dicho análisis. [67] Harper 2009 propone incluir tanto la evaluación estricta como la perezosa en el mismo lenguaje, utilizando el sistema de tipos del lenguaje para distinguirlas. [68]

Sistemas de tipos

Especialmente desde el desarrollo de la inferencia de tipos Hindley-Milner en la década de 1970, los lenguajes de programación funcional han tendido a utilizar el cálculo lambda tipado , rechazando todos los programas inválidos en tiempo de compilación y arriesgando errores falsos positivos , en oposición al cálculo lambda no tipado , que acepta todos los programas válidos en tiempo de compilación y arriesga errores falsos negativos , utilizado en Lisp y sus variantes (como Scheme ), ya que rechazan todos los programas inválidos en tiempo de ejecución cuando la información es suficiente para no rechazar programas válidos. El uso de tipos de datos algebraicos hace que la manipulación de estructuras de datos complejas sea conveniente; la presencia de una fuerte verificación de tipos en tiempo de compilación hace que los programas sean más confiables en ausencia de otras técnicas de confiabilidad como el desarrollo impulsado por pruebas , mientras que la inferencia de tipos libera al programador de la necesidad de declarar manualmente los tipos al compilador en la mayoría de los casos.

Algunos lenguajes funcionales orientados a la investigación, como Coq , Agda , Cayenne y Epigram, se basan en la teoría de tipos intuicionista , que permite que los tipos dependan de términos. Dichos tipos se denominan tipos dependientes . Estos sistemas de tipos no tienen inferencia de tipos decidible y son difíciles de entender y programar. [69] [70] [71] [72] Pero los tipos dependientes pueden expresar proposiciones arbitrarias en lógica de orden superior . A través del isomorfismo de Curry-Howard , entonces, los programas bien tipados en estos lenguajes se convierten en un medio para escribir pruebas matemáticas formales a partir de las cuales un compilador puede generar código certificado . Si bien estos lenguajes son principalmente de interés en la investigación académica (incluida la matemática formalizada ), también han comenzado a usarse en ingeniería. Compcert es un compilador para un subconjunto del lenguaje C que está escrito en Coq y verificado formalmente. [73]

Se puede implementar una forma limitada de tipos dependientes, denominada tipos de datos algebraicos generalizados (GADT), de manera que proporcione algunos de los beneficios de la programación con tipos dependientes y al mismo tiempo evite la mayoría de sus inconvenientes. [74] Los GADT están disponibles en el compilador Glasgow Haskell , en OCaml [75] y en Scala [76], y se han propuesto como complementos a otros lenguajes, incluidos Java y C#. [77]

Transparencia referencial

Los programas funcionales no tienen instrucciones de asignación, es decir, el valor de una variable en un programa funcional nunca cambia una vez definida. Esto elimina cualquier posibilidad de efectos secundarios porque cualquier variable puede reemplazarse con su valor real en cualquier punto de la ejecución. Por lo tanto, los programas funcionales son referencialmente transparentes. [78]

Consideremos la declaración de asignación de Cx=x * 10 , que cambia el valor asignado a la variable x. Digamos que el valor inicial de xera 1, entonces dos evaluaciones consecutivas de la variable xdan como resultado 10y 100respectivamente. Claramente, reemplazar x=x * 10con 10o 100le da al programa un significado diferente, por lo que la expresión no es referencialmente transparente. De hecho, las declaraciones de asignación nunca son referencialmente transparentes.

Ahora, consideremos otra función como es transparente, ya que no cambia implícitamente la entrada x y, por lo tanto, no tiene efectos secundarios . Los programas funcionales utilizan exclusivamente este tipo de función y, por lo tanto, son referencialmente transparentes.int plusone(int x) {return x+1;}

Estructuras de datos

Las estructuras de datos puramente funcionales suelen representarse de una manera diferente a sus contrapartes imperativas . [79] Por ejemplo, la matriz con tiempos de acceso y actualización constantes es un componente básico de la mayoría de los lenguajes imperativos, y muchas estructuras de datos imperativas, como la tabla hash y el montón binario , se basan en matrices. Las matrices pueden reemplazarse por mapas o listas de acceso aleatorio, que admiten una implementación puramente funcional, pero tienen tiempos de acceso y actualización logarítmicos . Las estructuras de datos puramente funcionales tienen persistencia , una propiedad de mantener las versiones anteriores de la estructura de datos sin modificar. En Clojure, las estructuras de datos persistentes se utilizan como alternativas funcionales a sus contrapartes imperativas. Los vectores persistentes, por ejemplo, utilizan árboles para la actualización parcial. Llamar al método insert dará como resultado la creación de algunos nodos, pero no de todos. [80]

Comparación con la programación imperativa

La programación funcional es muy diferente de la programación imperativa . Las diferencias más significativas surgen del hecho de que la programación funcional evita los efectos secundarios , que se utilizan en la programación imperativa para implementar el estado y la E/S. La programación funcional pura evita por completo los efectos secundarios y proporciona transparencia referencial.

En la programación imperativa antigua, rara vez se utilizan funciones de orden superior. Un programa imperativo tradicional podría utilizar un bucle para recorrer y modificar una lista. Por otro lado, un programa funcional probablemente utilizaría una función de "mapa" de orden superior que toma una función y una lista, generando y devolviendo una nueva lista aplicando la función a cada elemento de la lista.

Programación imperativa vs. programación funcional

Los siguientes dos ejemplos (escritos en JavaScript ) logran el mismo efecto: multiplican todos los números pares de una matriz por 10 y los suman todos, almacenando la suma final en la variable "resultado".

Bucle imperativo tradicional:

const numList = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]; deje que resultado = 0 ; para ( deje que i = 0 ; i < numList . length ; i ++ ) { si ( numList [ i ] % 2 === 0 ) { resultado += numList [ i ] * 10 ; } }                                     

Programación funcional con funciones de orden superior:

const resultado = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] .filter ( n => n % 2 === 0 ) .map ( a => a * 10 ) .reduce ( ( a , b ) = > a + b , 0 ) ;                               

A veces, las abstracciones que ofrece la programación funcional pueden llevar al desarrollo de un código más robusto que evite ciertos problemas que pueden surgir al construir sobre una gran cantidad de código complejo e imperativo, como errores de un dígito (ver la décima regla de Greenspun ).

Simulación de estado

Hay tareas (por ejemplo, mantener el saldo de una cuenta bancaria) que a menudo parecen implementarse de manera más natural con el estado. La programación funcional pura realiza estas tareas, y las tareas de E/S como aceptar la entrada del usuario e imprimir en la pantalla, de una manera diferente.

El lenguaje de programación funcional puro Haskell las implementa utilizando mónadas , derivadas de la teoría de categorías . [81] Las mónadas ofrecen una forma de abstraer ciertos tipos de patrones computacionales, incluyendo (pero no limitado a) el modelado de cálculos con estado mutable (y otros efectos secundarios como E/S) de manera imperativa sin perder pureza. Si bien las mónadas existentes pueden ser fáciles de aplicar en un programa, dadas las plantillas y ejemplos apropiados, muchos estudiantes las encuentran difíciles de entender conceptualmente, por ejemplo, cuando se les pide que definan nuevas mónadas (lo que a veces es necesario para ciertos tipos de bibliotecas). [82]

Los lenguajes funcionales también simulan estados al pasar estados inmutables. Esto se puede hacer haciendo que una función acepte el estado como uno de sus parámetros y devuelva un nuevo estado junto con el resultado, dejando el estado anterior sin cambios. [83]

Los lenguajes funcionales impuros suelen incluir un método más directo para gestionar el estado mutable. Clojure , por ejemplo, utiliza referencias gestionadas que se pueden actualizar aplicando funciones puras al estado actual. Este tipo de enfoque permite la mutabilidad y, al mismo tiempo, promueve el uso de funciones puras como la forma preferida de expresar los cálculos. [ cita requerida ]

Se han desarrollado métodos alternativos, como la lógica de Hoare y la unicidad, para rastrear los efectos secundarios en los programas. Algunos lenguajes de investigación modernos utilizan sistemas de efectos para hacer explícita la presencia de efectos secundarios. [ cita requerida ]

Problemas de eficiencia

Los lenguajes de programación funcional son típicamente menos eficientes en su uso de CPU y memoria que los lenguajes imperativos como C y Pascal . [84] Esto está relacionado con el hecho de que algunas estructuras de datos mutables como las matrices tienen una implementación muy sencilla utilizando el hardware actual. Se puede acceder a las matrices planas de manera muy eficiente con CPU profundamente segmentadas, precargarlas de manera eficiente a través de cachés (sin persecución compleja de punteros) o manejarlas con instrucciones SIMD. Tampoco es fácil crear sus contrapartes inmutables de propósito general igualmente eficientes. Para lenguajes puramente funcionales, la desaceleración del peor caso es logarítmica en el número de celdas de memoria utilizadas, porque la memoria mutable puede representarse mediante una estructura de datos puramente funcional con tiempo de acceso logarítmico (como un árbol equilibrado). [85] Sin embargo, tales desaceleraciones no son universales. Para programas que realizan cálculos numéricos intensivos, los lenguajes funcionales como OCaml y Clean son solo ligeramente más lentos que C según The Computer Language Benchmarks Game . [86] Para los programas que manejan matrices grandes y bases de datos multidimensionales , se diseñaron lenguajes funcionales de matrices (como J y K ) con optimizaciones de velocidad.

La inmutabilidad de los datos puede, en muchos casos, llevar a la eficiencia de la ejecución al permitir que el compilador haga suposiciones que no son seguras en un lenguaje imperativo, aumentando así las oportunidades de expansión en línea . [87] Incluso si la copia involucrada que puede parecer implícita cuando se trata con estructuras de datos inmutables persistentes puede parecer computacionalmente costosa, algunos lenguajes de programación funcional, como Clojure, resuelven este problema implementando mecanismos para compartir memoria de manera segura entre datos formalmente inmutables . [88] Rust se distingue por su enfoque de la inmutabilidad de datos que involucra referencias inmutables [89] y un concepto llamado tiempos de vida. [90]

Los datos inmutables con separación de identidad y estado y los esquemas de nada compartido también pueden ser potencialmente más adecuados para la programación concurrente y paralela en virtud de reducir o eliminar el riesgo de ciertos peligros de concurrencia, ya que las operaciones concurrentes suelen ser atómicas y esto permite eliminar la necesidad de bloqueos. Así es como java.util.concurrentse implementan, por ejemplo, las clases, donde algunas de ellas son variantes inmutables de las clases correspondientes que no son adecuadas para el uso concurrente. [91] Los lenguajes de programación funcional a menudo tienen un modelo de concurrencia que, en lugar de estado compartido y sincronización, aprovecha los mecanismos de paso de mensajes (como el modelo de actor , donde cada actor es un contenedor para el estado, el comportamiento, los actores secundarios y una cola de mensajes). [92] [93] Este enfoque es común en Erlang / Elixir o Akka .

La evaluación perezosa también puede acelerar el programa, incluso asintóticamente, mientras que puede ralentizarlo como máximo por un factor constante (sin embargo, puede introducir fugas de memoria si se utiliza de forma incorrecta). Launchbury 1993 [67] analiza cuestiones teóricas relacionadas con las fugas de memoria de la evaluación perezosa, y O'Sullivan et al. 2008 [94] dan algunos consejos prácticos para analizarlas y solucionarlas. Sin embargo, las implementaciones más generales de la evaluación perezosa que hacen un uso extensivo de código y datos desreferenciados tienen un rendimiento deficiente en procesadores modernos con tuberías profundas y cachés de varios niveles (donde una falla de caché puede costar cientos de ciclos) [ cita requerida ] .

Costo de abstracción

Es posible que algunos lenguajes de programación funcional no optimicen abstracciones como funciones de orden superior como " map " o " filter " de manera tan eficiente como las operaciones imperativas subyacentes. Considere, como ejemplo, las siguientes dos formas de verificar si 5 es un número par en Clojure :

( ¿par? 5 ) ( .igual a ( mod 5 2 ) 0 )     

Cuando se realizó una evaluación comparativa con la herramienta Criterium en una PC Ryzen 7900X GNU/Linux en un Leiningen REPL 2.11.2, ejecutándose en Java VM versión 22 y Clojure versión 1.11.1, la primera implementación, que se implementa como:

( defn even? "Devuelve verdadero si n es par, lanza una excepción si n no es un entero" { :added "1.0" :static true } [ n ] ( if ( entire? n ) ( zero? ( bit-and ( clojure.lang.RT/uncheckedLongCast n ) 1 )) ( throw ( IllegalArgumentException. ( str "El argumento debe ser un entero: " n )))))               

tiene un tiempo de ejecución medio de 4,76 ms, mientras que el segundo, en el que .equalsse invoca directamente el método Java subyacente , tiene un tiempo de ejecución medio de 2,8 μs, aproximadamente 1700 veces más rápido. Parte de esto se puede atribuir a la comprobación de tipos y al manejo de excepciones implicados en la implementación de even?, así que tomemos como ejemplo la biblioteca lo para Go , que implementa varias funciones de orden superior comunes en lenguajes de programación funcional utilizando genéricos . En un punto de referencia proporcionado por el autor de la biblioteca, la llamada mapes un 4% más lenta que un forbucle equivalente y tiene el mismo perfil de asignación , [95] lo que se puede atribuir a varias optimizaciones del compilador, como la inserción en línea . [96]

Una característica distintiva de Rust son las abstracciones de costo cero . Esto significa que su uso no impone ninguna sobrecarga adicional en tiempo de ejecución. Esto se logra gracias a que el compilador utiliza un desenrollado de bucle , donde cada iteración de un bucle, ya sea imperativo o que utilice iteradores, se convierte en una instrucción de ensamblaje independiente , sin la sobrecarga del código de control del bucle. Si una operación iterativa escribe en una matriz, los elementos de la matriz resultante se almacenarán en registros específicos de la CPU , lo que permite un acceso en tiempo constante en tiempo de ejecución. [97]

Programación funcional en lenguajes no funcionales

Es posible utilizar un estilo funcional de programación en lenguajes que tradicionalmente no se consideran lenguajes funcionales. [98] Por ejemplo, tanto D [99] como Fortran 95 [60] admiten explícitamente funciones puras.

JavaScript , Lua , [100] Python y Go [101] tuvieron funciones de primera clase desde su inicio. [102] Python tuvo soporte para " lambda ", " map ", " reduce " y " filter " en 1994, así como cierres en Python 2.2, [103] aunque Python 3 relegó "reduce" al functoolsmódulo de biblioteca estándar. [104] Se han introducido funciones de primera clase en otros lenguajes principales como PHP 5.3, Visual Basic 9 , C# 3.0, C++11 y Kotlin . [28] [ cita requerida ]

En PHP, las clases anónimas , los cierres y las lambdas son totalmente compatibles. Se están desarrollando bibliotecas y extensiones de lenguaje para estructuras de datos inmutables con el fin de facilitar la programación en el estilo funcional.

En Java , las clases anónimas a veces se pueden usar para simular cierres; [105] sin embargo, las clases anónimas no siempre son reemplazos adecuados para los cierres porque tienen capacidades más limitadas. [106] Java 8 admite expresiones lambda como reemplazo para algunas clases anónimas. [107]

En C# , las clases anónimas no son necesarias, ya que los cierres y las lambdas son totalmente compatibles. Se están desarrollando bibliotecas y extensiones de lenguaje para estructuras de datos inmutables con el fin de facilitar la programación en el estilo funcional de C#.

Muchos patrones de diseño orientados a objetos se pueden expresar en términos de programación funcional: por ejemplo, el patrón de estrategia simplemente dicta el uso de una función de orden superior, y el patrón de visitante corresponde aproximadamente a un catamorfismo o pliegue .

De manera similar, la idea de datos inmutables de la programación funcional a menudo se incluye en lenguajes de programación imperativos, [108] por ejemplo la tupla en Python, que es una matriz inmutable, y Object.freeze() en JavaScript. [109]

Comparación con la programación lógica

La programación lógica puede considerarse como una generalización de la programación funcional, en la que las funciones son un caso especial de relaciones. [110] Por ejemplo, la función, madre(X) = Y, (cada X tiene sólo una madre Y) puede representarse mediante la relación madre(X, Y). Mientras que las funciones tienen un patrón estricto de entrada-salida de argumentos, las relaciones pueden consultarse con cualquier patrón de entradas y salidas. Considere el siguiente programa lógico:

madre ( charles ,  elizabeth ). madre ( harry ,  diana ).

Se puede consultar el programa, como si fuera un programa funcional, para generar madres a partir de niños:

?-  madre ( harry ,  X ). X  =  diana . ?-  madre ( charles ,  X ). X  =  elizabeth .

Pero también se puede consultar al revés , para generar hijos:

?-  madre ( X ,  elizabeth ). X  =  charles . ?-  madre ( X ,  diana ). X  =  harry .

Incluso se puede utilizar para generar todas las instancias de la relación madre:

?-  madre ( X ,  Y ). X  =  Carlos , Y  =  Isabel . X  =  harry , Y  =  diana .

En comparación con la sintaxis relacional, la sintaxis funcional es una notación más compacta para funciones anidadas. Por ejemplo, la definición de abuela materna en sintaxis funcional se puede escribir en la forma anidada:

abuela_materna ( X )  =  madre ( madre ( X )).

La misma definición en notación relacional debe escribirse en forma no anidada:

abuela_materna ( X ,  Y )  :-  madre ( X ,  Z ),  madre ( Z ,  Y ).

Aquí :-significa si y , significa y .

Sin embargo, la diferencia entre ambas representaciones es simplemente sintáctica. En Ciao Prolog, las relaciones se pueden anidar, como las funciones en la programación funcional: [111]

abuelo ( a) ( X )  :=  padre ( a) ( padre ( a) ( X )). padre ( a ) (X )  :=  madre ( X ). padre ( a) ( X )  :=  padre ( a) ( X ).madre ( charles )  :=  elizabeth . padre ( charles )  :=  phillip . madre ( harry )  :=  diana . padre ( harry )  :=  charles .?-  abuelo ( X , Y ). X  =  harry , Y  =  elizabeth . X  =  harry , Y  =  phillip .

Ciao transforma la notación funcional en forma relacional y ejecuta el programa lógico resultante utilizando la estrategia de ejecución estándar de Prolog.

Aplicaciones

Editores de texto

Emacs , una familia de editores de texto altamente extensible, utiliza su propio dialecto Lisp para escribir complementos. El autor original de la implementación más popular de Emacs, GNU Emacs y Emacs Lisp, Richard Stallman considera a Lisp uno de sus lenguajes de programación favoritos. [112]

Helix, desde la versión 24.03, admite la vista previa de AST como S-expresiones , que también son la característica principal de la familia de lenguajes de programación Lisp. [113]

Hojas de cálculo

Las hojas de cálculo pueden considerarse una forma de sistema de programación funcional puro, de orden cero y de evaluación estricta. [114] Sin embargo, las hojas de cálculo generalmente carecen de funciones de orden superior, así como de reutilización de código y, en algunas implementaciones, también carecen de recursión. Se han desarrollado varias extensiones para programas de hojas de cálculo para habilitar funciones de orden superior y reutilizables, pero hasta ahora siguen siendo principalmente de naturaleza académica. [115]

Academia

La programación funcional es un área activa de investigación en el campo de la teoría de los lenguajes de programación . Existen varios lugares de publicación revisados ​​por pares que se centran en la programación funcional, entre ellos la Conferencia Internacional sobre Programación Funcional , el Journal of Functional Programming y el Simposio sobre Tendencias en Programación Funcional .

Industria

La programación funcional se ha empleado en una amplia gama de aplicaciones industriales. Por ejemplo, Erlang , que fue desarrollado por la empresa sueca Ericsson a fines de la década de 1980, se utilizó originalmente para implementar sistemas de telecomunicaciones tolerantes a fallas , [11] pero desde entonces se ha vuelto popular para construir una gama de aplicaciones en empresas como Nortel , Facebook , Électricité de France y WhatsApp . [10] [12] [116] [117] [118] Scheme , un dialecto de Lisp , se utilizó como base para varias aplicaciones en las primeras computadoras Apple Macintosh [3] [4] y se ha aplicado a problemas como software de simulación de entrenamiento [5] y control de telescopios . [6] OCaml , que se introdujo a mediados de la década de 1990, ha tenido un uso comercial en áreas como análisis financiero, [14] verificación de controladores , programación de robots industriales y análisis estático de software integrado . [15] Haskell , aunque inicialmente fue pensado como un lenguaje de investigación, [17] también se ha aplicado en áreas como sistemas aeroespaciales, diseño de hardware y programación web. [16] [17]

Otros lenguajes de programación funcional que se han utilizado en la industria incluyen Scala , [119] F# , [18] [19] Wolfram Language , [7] Lisp , [120] Standard ML [121] [122] y Clojure. [123] Scala se ha utilizado ampliamente en la ciencia de datos , [124] mientras que ClojureScript , [125] Elm [126] o PureScript [127] son ​​algunos de los lenguajes de programación frontend funcionales utilizados en producción. El marco Phoenix de Elixir también se utiliza en algunos proyectos comerciales relativamente populares, como Font Awesome o la plataforma de anuncios clasificados de Allegro (una de las plataformas de comercio electrónico más grandes de Polonia) [128] Allegro Lokalnie. [129]

Las "plataformas" funcionales han sido populares en finanzas para el análisis de riesgos (particularmente en los grandes bancos de inversión). Los factores de riesgo se codifican como funciones que forman gráficos interdependientes (categorías) para medir las correlaciones en los cambios del mercado, de manera similar a las optimizaciones de base de Gröbner , pero también para marcos regulatorios como el Análisis y Revisión Integral de Capital . Dado el uso de variaciones de OCaml y Caml en finanzas, estos sistemas a veces se consideran relacionados con una máquina abstracta categórica . La programación funcional está fuertemente influenciada por la teoría de categorías . [ cita requerida ]

Educación

Muchas universidades enseñan programación funcional. [130] [131] [132] [133] Algunas lo tratan como un concepto introductorio de programación [133] mientras que otras enseñan primero métodos de programación imperativa. [132] [134]

Fuera de la informática, la programación funcional se utiliza para enseñar resolución de problemas, conceptos algebraicos y geométricos. [135] También se ha utilizado para enseñar mecánica clásica, como en el libro Estructura e interpretación de la mecánica clásica .

En particular, Scheme ha sido una opción relativamente popular para enseñar programación durante años. [136] [137]

Véase también

Notas y referencias

  1. ^ Hudak, Paul (septiembre de 1989). "Concepción, evolución y aplicación de lenguajes de programación funcional" (PDF) . ACM Computing Surveys . 21 (3): 359–411. doi :10.1145/72551.72554. S2CID  207637854. Archivado desde el original (PDF) el 2016-01-31 . Consultado el 2013-08-10 .
  2. ^ ab Hughes, John (1984). "Por qué es importante la programación funcional".
  3. ^ ab Clinger, Will (1987). "Multitarea y MacScheme". MacTech . 3 (12) . Consultado el 28 de agosto de 2008 .
  4. ^ ab Hartheimer, Anne (1987). "Programación de un editor de texto en MacScheme+Toolsmith". MacTech . 3 (1). Archivado desde el original el 29 de junio de 2011 . Consultado el 28 de agosto de 2008 .
  5. ^ ab Kidd, Eric. Terrorism Response Training in Scheme. CUFP 2007. Archivado desde el original el 21 de diciembre de 2010. Consultado el 26 de agosto de 2009 .
  6. ^ ab Cleis, Richard. Esquema en el espacio. CUFP 2006. Archivado desde el original el 27 de mayo de 2010. Consultado el 26 de agosto de 2009 .
  7. ^ ab "Guía del lenguaje Wolfram: programación funcional". 2015. Consultado el 24 de agosto de 2015 .
  8. ^ "Lenguaje de programación funcional vs. procedimental". Departamento de Matemática Aplicada . Universidad de Colorado. Archivado desde el original el 13 de noviembre de 2007. Consultado el 28 de agosto de 2006 .
  9. ^ "Scripting basado en estados en Uncharted 2" (PDF) . Archivado desde el original (PDF) el 2012-12-15 . Consultado el 2011-08-08 .
  10. ^ ab "¿Quién utiliza Erlang para el desarrollo de productos?". Preguntas frecuentes sobre Erlang . Consultado el 27 de abril de 2018 .
  11. ^ ab Armstrong, Joe (junio de 2007). "Una historia de Erlang". Actas de la tercera conferencia ACM SIGPLAN sobre Historia de los lenguajes de programación . Tercera conferencia ACM SIGPLAN sobre Historia de los lenguajes de programación. San Diego, California. doi :10.1145/1238844.1238850. ISBN 9781595937667.
  12. ^ ab Larson, Jim (marzo de 2009). "Erlang para programación concurrente". Comunicaciones de la ACM . 52 (3): 48. doi : 10.1145/1467247.1467263 . S2CID  524392.
  13. ^ "El lenguaje de programación Elixir" . Consultado el 14 de febrero de 2021 .
  14. ^ ab Minsky, Yaron; Weeks, Stephen (julio de 2008). "Caml Trading: experiencias con programación funcional en Wall Street". Journal of Functional Programming . 18 (4): 553–564. doi : 10.1017/S095679680800676X (inactivo 2024-08-12). S2CID  30955392.{{cite journal}}: CS1 maint: DOI inactivo a partir de agosto de 2024 ( enlace )
  15. ^ ab Leroy, Xavier. Algunos usos de Caml en la industria (PDF) . CUFP 2007. Archivado desde el original (PDF) el 2011-10-08 . Consultado el 2009-08-26 .
  16. ^ ab "Haskell en la industria". Wiki de Haskell . Consultado el 26 de agosto de 2009. Haskell tiene una amplia gama de usos comerciales, desde la industria aeroespacial y de defensa hasta las finanzas, pasando por empresas emergentes de Internet, firmas de diseño de hardware y fabricantes de cortadoras de césped.
  17. ^ abc Hudak, Paul ; Hughes, J.; Jones, SP; Wadler, P. (junio de 2007). Una historia de Haskell: ser perezoso con la clase. Tercera conferencia ACM SIGPLAN sobre historia de los lenguajes de programación. San Diego, California. doi :10.1145/1238844.1238856 . Consultado el 26 de septiembre de 2013 .
  18. ^ ab Mansell, Howard (2008). Finanzas cuantitativas en F#. CUFP 2008. Archivado desde el original el 8 de julio de 2015. Consultado el 29 de agosto de 2009 .
  19. ^ ab Peake, Alex (2009). La primera aplicación sustancial de una línea de negocio en F#. CUFP 2009. Archivado desde el original el 17 de octubre de 2009. Consultado el 29 de agosto de 2009 .
  20. ^ de Moura, Leonardo; Ullrich, Sebastian (julio de 2021). "El demostrador de teoremas y lenguaje de programación Lean 4". Notas de clase en inteligencia artificial . Conferencia sobre deducción automatizada. Vol. 12699. págs. doi : 10.1007/978-3-030-79876-5_37 . ISSN  1611-3349.
  21. ^ Banz, Matt (27 de junio de 2017). "Introducción a la programación funcional en JavaScript". Opensource.com . Consultado el 9 de enero de 2021 .
  22. ^ "El programa de conferencias de useR! 2006 incluye artículos sobre el uso comercial de R". R-project.org. 2006-06-08 . Consultado el 20 de junio de 2011 .
  23. ^ Chambers, John M. (1998). Programación con datos: una guía para el lenguaje S. Springer Verlag. págs. 67–70. ISBN. 978-0-387-98503-9.
  24. ^ Novatchev, Dimitre. "El lenguaje de programación funcional XSLT: una prueba mediante ejemplos" . Consultado el 27 de mayo de 2006 .
  25. ^ Mertz, David. "Paradigmas de programación XML (parte cuatro): Programación funcional enfocada al procesamiento XML". IBM developerWorks . Consultado el 27 de mayo de 2006 .
  26. ^ Chamberlin, Donald D .; Boyce, Raymond F. (1974). "SEQUEL: Un lenguaje de consulta estructurado en inglés". Actas de la ACM SIGFIDET de 1974 : 249–264.
  27. ^ Programación funcional con C# - Simon Painter - NDC Oslo 2020, 8 de agosto de 2021, archivado desde el original el 2021-10-30 , consultado el 2021-10-23
  28. ^ ab "Programación funcional - Lenguaje de programación Kotlin". Kotlin . Consultado el 1 de mayo de 2019 .
  29. ^ Dominus, Mark J. (2005). Perl de orden superior . Morgan Kaufmann . ISBN 978-1-55860-701-9.
  30. ^ Holywell, Simón (2014). Programación funcional en PHP . php[arquitecto]. ISBN 9781940111056.
  31. ^ The Cain Gang Ltd. "Metaclases de Python: ¿Quién? ¿Por qué? ¿Cuándo?" (PDF) . Archivado desde el original (PDF) el 30 de mayo de 2009. Consultado el 27 de junio de 2009 .
  32. ^ "GopherCon 2020: Dylan Meeus - Programación funcional con Go". YouTube . 22 de diciembre de 2020.
  33. ^ "Características del lenguaje funcional: iteradores y cierres - El lenguaje de programación Rust". doc.rust-lang.org . Consultado el 9 de enero de 2021 .
  34. ^ Vanderbauwhede, Wim (18 de julio de 2020). «Código más limpio con programación funcional». Archivado desde el original el 28 de julio de 2020. Consultado el 6 de octubre de 2020 .
  35. ^ "Scala eficaz". Wiki de Scala . Archivado desde el original el 19 de junio de 2012. Consultado el 21 de febrero de 2012. Scala eficaz.
  36. ^ "Documentación del paquete java.util.function desde Java 8 (también conocido como Java 1.8)" . Consultado el 16 de junio de 2021 .
  37. ^ Rodger, Richard (11 de diciembre de 2017). El Tao de los microservicios . Manning. ISBN 9781638351733.
  38. ^ Turing, AM (1937). "Computabilidad y λ-definibilidad". Revista de lógica simbólica . 2 (4). Cambridge University Press: 153–163. doi :10.2307/2268280. JSTOR  2268280. S2CID  2317046.
  39. ^ Haskell Brooks Curry; Robert Feys (1958). Combinatory Logic . North-Holland Publishing Company . Consultado el 10 de febrero de 2013 .
  40. ^ Church, A. (1940). "Una formulación de la teoría simple de tipos". Revista de lógica simbólica . 5 (2): 56–68. doi :10.2307/2266170. JSTOR  2266170. S2CID  15889861.
  41. ^ McCarthy, John (junio de 1978). Historia de Lisp (PDF) . Historia de los lenguajes de programación . Los Ángeles, CA. pp. 173–185. doi :10.1145/800025.808387.
  42. ^ John McCarthy (1960). "Funciones recursivas de expresiones simbólicas y su cálculo por máquina, Parte I". (PDF) . Comunicaciones de la ACM . 3 (4). ACM Nueva York, NY, EE. UU.: 184–195. doi :10.1145/367177.367199. S2CID  1489409.
  43. ^ Guy L. Steele; Richard P. Gabriel (febrero de 1996). "La evolución de Lisp". Historia de los lenguajes de programación---II (PDF) . pp. 233–330. doi :10.1145/234286.1057818. ISBN 978-0-201-89502-5. Número de identificación del sujeto  47047140.
  44. ^ Las memorias de Herbert A. Simon (1991), Models of My Life pp.189-190 ISBN 0-465-04640-1 afirman que él, Al Newell y Cliff Shaw son "... considerados comúnmente como los padres de [el] campo de la inteligencia artificial", por escribir Logic Theorist , un programa que demostraba teoremas de Principia Mathematica automáticamente. Para lograrlo, tuvieron que inventar un lenguaje y un paradigma que, visto retrospectivamente, incorpora la programación funcional. 
  45. ^ Landin, Peter J. (1964). "La evaluación mecánica de expresiones". The Computer Journal . 6 (4). British Computer Society : 308–320. doi : 10.1093/comjnl/6.4.308 .
  46. ^ Diehl, Stephan; Hartel, Pieter; Sestoft, Peter (2000). "Máquinas abstractas para la implementación de lenguajes de programación". Future Generation Computer Systems . Vol. 16. págs. 739–751.
  47. ^ Landin, Peter J. (febrero de 1965a). "Correspondencia entre ALGOL 60 y la notación Lambda de Church: parte I". Comunicaciones de la ACM . 8 (2). Association for Computing Machinery : 89–101. doi : 10.1145/363744.363749 . S2CID  6505810.
  48. ^ Landin, Peter J. (marzo de 1965b). "Una correspondencia entre ALGOL 60 y la notación Lambda de Church: parte II". Comunicaciones de la ACM . 8 (3). Association for Computing Machinery : 158–165. doi : 10.1145/363791.363804 . S2CID  15781851.
  49. ^ Landin, Peter J. (marzo de 1966b). "Los siguientes 700 lenguajes de programación". Comunicaciones de la ACM . 9 (3). Association for Computing Machinery : 157–166. doi : 10.1145/365230.365257 . S2CID  13409665.
  50. ^ Backus, J. (1978). "¿Puede la programación liberarse del estilo von Neumann?: Un estilo funcional y su álgebra de programas". Comunicaciones de la ACM . 21 (8): 613–641. doi : 10.1145/359576.359579 .
  51. ^ RM Burstall. Consideraciones de diseño para un lenguaje de programación funcional. Ponencia invitada, Proc. Infotech State of the Art Conf. "La revolución del software", Copenhague, 45–57 (1977)
  52. ^ RM Burstall y J. Darlington. Un sistema de transformación para desarrollar programas recursivos. Journal of the Association for Computing Machinery 24(1):44–67 (1977)
  53. ^ RM Burstall, DB MacQueen y DT Sannella. HOPE: un lenguaje aplicativo experimental. Actas de la Conferencia LISP de 1980, Stanford, 136–143 (1980).
  54. ^ "¡Haga que descubrir la función asignar() sea más fácil!". OpenSCAD . Archivado desde el original el 19 de abril de 2023.
  55. ^ Peter Bright (13 de marzo de 2018). "A los desarrolladores les encantan los nuevos lenguajes de moda, pero ganan más con la programación funcional". Ars Technica .
  56. ^ John Leonard (24 de enero de 2017). "El ascenso sigiloso de la programación funcional". Computación.
  57. ^ Leo Cheung (9 de mayo de 2017). "¿La programación funcional es mejor para tu startup?". InfoWorld .
  58. ^ Sean Tull - Categorías monoidales para el análisis de conceptos formales.
  59. ^ Pountain, Dick. "Functional Programming Comes of Age". Byte (agosto de 1994) . Archivado desde el original el 27 de agosto de 2006. Consultado el 31 de agosto de 2006 .
  60. ^ ab "ISO/IEC JTC 1/SC 22/WG5/N2137 – Borrador del Comité Fortran 2015 (J3/17-007r2)" (PDF) . Organización Internacional de Normalización. 6 de julio de 2017. págs. 336–338.
  61. ^ "Informe revisado^6 sobre el esquema de lenguaje algorítmico". R6rs.org . Consultado el 21 de marzo de 2013 .
  62. ^ "Informe revisado^6 sobre el esquema de lenguaje algorítmico: fundamento". R6rs.org . Consultado el 21 de marzo de 2013 .
  63. ^ Clinger, William (1998). "Recursión de cola adecuada y eficiencia espacial". Actas de la conferencia ACM SIGPLAN 1998 sobre diseño e implementación de lenguajes de programación - PLDI '98 . págs. 174–185. doi :10.1145/277650.277719. ISBN 0897919874. Número de identificación del sujeto  16812984.
  64. ^ Baker, Henry (1994). "CONS no debería CONS en sus argumentos, parte II: Cheney sobre la MTA" Archivado desde el original el 2006-03-03 . Consultado el 2020-04-29 .
  65. ^ Turner, DA (28 de julio de 2004). "Programación funcional total". Revista de informática universal . 10 (7): 751–768. doi :10.3217/jucs-010-07-0751.
  66. ^ La implementación de lenguajes de programación funcional. Simon Peyton Jones, publicado por Prentice Hall, 1987
  67. ^ ab Launchbury, John (marzo de 1993). Una semántica natural para la evaluación perezosa . Simposio sobre principios de lenguajes de programación. Charleston, Carolina del Sur: ACM . págs. 144-154. doi : 10.1145/158511.158618 .
  68. ^ Robert W. Harper (2009). Fundamentos prácticos para lenguajes de programación (PDF) . Archivado desde el original (PDF) el 7 de abril de 2016.
  69. ^ Huet, Gérard P. (1973). "La indecidibilidad de la unificación en la lógica de tercer orden". Información y control . 22 (3): 257–267. doi :10.1016/s0019-9958(73)90301-x.
  70. ^ Huet, Gérard (septiembre de 1976). Resolución de ecuaciones en los idiomas de orden 1,2,... ω (Ph.D.) (en francés). Universidad de París VII.
  71. ^ Huet, Gérard (2002). "Unificación de orden superior 30 años después" (PDF) . En Carreño, V.; Muñoz, C.; Tahar, S. (eds.). Actas, 15.ª Conferencia Internacional TPHOL . LNCS. Vol. 2410. Springer. pp. 3–12.
  72. ^ Wells, JB (1993). "La tipabilidad y la comprobación de tipos en el cálculo lambda de segundo orden son equivalentes e indecidibles". Tech. Rep. 93-011 : 176–185. CiteSeerX 10.1.1.31.3590 . 
  73. ^ Leroy, Xavier (17 de septiembre de 2018). "El compilador verificado Compcert".
  74. ^ Peyton Jones, Simon; Vytiniotis, Dimitrios; Weirich, Stephanie ; Geoffrey Washburn (abril de 2006). "Inferencia de tipos basada en unificación simple para GADT". Icfp 2006 : 50–61.
  75. ^ "Manual de OCaml". caml.inria.fr . Consultado el 8 de marzo de 2021 .
  76. ^ "Tipos de datos algebraicos". Documentación de Scala . Consultado el 8 de marzo de 2021 .
  77. ^ Kennedy, Andrew; Russo, Claudio V. (octubre de 2005). Tipos de datos algebraicos generalizados y programación orientada a objetos (PDF) . OOPSLA. San Diego, California: ACM . doi :10.1145/1094811.1094814. ISBN. 9781595930316Archivado desde el original el 29 de diciembre de 2006.
  78. ^ Hughes, John. "Por qué es importante la programación funcional" (PDF) . Universidad Tecnológica de Chalmers .
  79. ^ Estructuras de datos puramente funcionales por Chris Okasaki , Cambridge University Press , 1998, ISBN 0-521-66350-4 
  80. ^ L'orange, Jean Niklas. "Polymatheia - Entendiendo el vector persistente de Clojure, pt. 1". Polymatheia . Consultado el 13 de noviembre de 2018 .
  81. ^ Michael Barr, Charles Well - Teoría de categorías para la informática.
  82. ^ Newbern, J. "Todo sobre las mónadas: una guía completa sobre la teoría y la práctica de la programación monádica en Haskell" . Consultado el 14 de febrero de 2008 .
  83. ^ "Trece maneras de mirar a una tortuga". fF# por diversión y beneficio . Consultado el 13 de noviembre de 2018 .
  84. ^ Paulson, Larry C. (28 de junio de 1996). ML para el programador en activo. Cambridge University Press. ISBN 978-0-521-56543-1. Recuperado el 10 de febrero de 2013 .
  85. ^ Spiewak, Daniel (26 de agosto de 2008). "Implementación de vectores persistentes en Scala". Code Commit . Archivado desde el original el 23 de septiembre de 2015 . Consultado el 17 de abril de 2012 .
  86. ^ "¿Qué programas son más rápidos? | Juego de benchmarks de lenguajes informáticos". benchmarksgame.alioth.debian.org. Archivado desde el original el 20 de mayo de 2013. Consultado el 20 de junio de 2011 .
  87. ^ Igor Pechtchanski; Vivek Sarkar (2005). "Especificación de inmutabilidad y sus aplicaciones". Concurrencia y computación: práctica y experiencia . 17 (5–6): 639–662. doi :10.1002/cpe.853. S2CID  34527406.
  88. ^ "Una mirada en profundidad a las colecciones de Clojure". InfoQ . Consultado el 29 de abril de 2024 .
  89. ^ "Referencias y préstamos: el lenguaje de programación Rust". doc.rust-lang.org . Consultado el 29 de abril de 2024 .
  90. ^ "Validación de referencias con tiempos de vida: el lenguaje de programación Rust". doc.rust-lang.org . Consultado el 29 de abril de 2024 .
  91. ^ "Colecciones concurrentes (Tutoriales de Java™ > Clases Java esenciales > Concurrencia)". docs.oracle.com . Consultado el 29 de abril de 2024 .
  92. ^ "Comprensión del modelo de actor para crear sistemas distribuidos de alto rendimiento y sin bloqueos - Scaleyourapp". scaleyourapp.com . 2023-01-28 . Consultado el 2024-04-29 .
  93. ^ Cesarini, Francesco; Thompson, Simon (2009). Programación Erlang: un enfoque concurrente para el desarrollo de software (1.ª ed.). O'Reilly Media, Inc. (publicado el 11 de junio de 2009). pág. 6. ISBN 978-0-596-55585-6.
  94. ^ "Capítulo 25. Creación de perfiles y optimización". Book.realworldhaskell.org . Consultado el 20 de junio de 2011 .
  95. ^ Berthe, Samuel (29 de abril de 2024), samber / lo , consultado el 29 de abril de 2024
  96. ^ "Go Wiki: Optimizaciones del compilador y del tiempo de ejecución: el lenguaje de programación Go". go.dev . Consultado el 29 de abril de 2024 .
  97. ^ "Comparación de rendimiento: bucles frente a iteradores: el lenguaje de programación Rust". doc.rust-lang.org . Consultado el 29 de abril de 2024 .
  98. ^ Hartel, Pieter; Henk Muller; Hugh Glaser (marzo de 2004). "La experiencia de Functional C" (PDF) . Journal of Functional Programming . 14 (2): 129–135. doi :10.1017/S0956796803004817. S2CID  32346900. Archivado desde el original (PDF) el 2011-07-19 . Consultado el 2006-05-28 .; David Mertz. "Programación funcional en Python, parte 3". IBM developerWorks . Archivado desde el original el 16 de octubre de 2007. Consultado el 17 de septiembre de 2006 .(Parte 1, Parte 2)
  99. ^ "Funciones: lenguaje de programación D 2.0". Digital Mars. 30 de diciembre de 2012.
  100. ^ "Preguntas frecuentes no oficiales de Lua (uFAQ)".
  101. ^ "Funciones de primera clase en Go: el lenguaje de programación Go". golang.org . Consultado el 4 de enero de 2021 .
  102. ^ Eich, Brendan (3 de abril de 2008). "Popularidad".
  103. ^ van Rossum, Guido (21 de abril de 2009). "Orígenes de las características "funcionales" de Python" . Consultado el 27 de septiembre de 2012 .
  104. ^ "functools — Funciones y operaciones de orden superior en objetos invocables". Python Software Foundation. 2011-07-31 . Consultado el 2011-07-31 .
  105. ^ Skarsaune, Martin (2008). El proyecto SICS Java Port Traducción automática de un gran sistema orientado a objetos de Smalltalk a Java .
  106. ^ Gosling, James. "Closures". James Gosling: on the Java Road . Oracle. Archivado desde el original el 14 de abril de 2013. Consultado el 11 de mayo de 2013 .
  107. ^ Williams, Michael (8 de abril de 2013). "Guía rápida de Java SE 8 Lambda".
  108. ^ Bloch, Joshua (2008). "Elemento 15: Minimizar la mutabilidad". Effective Java (Segunda edición). Addison-Wesley. ISBN 978-0321356680.
  109. ^ "Object.freeze() - JavaScript | MDN". developer.mozilla.org . Consultado el 4 de enero de 2021 . El método Object.freeze() congela un objeto. Un objeto congelado ya no se puede modificar; congelar un objeto impide que se le agreguen nuevas propiedades, que se eliminen las propiedades existentes, impide cambiar la enumerabilidad, la configurabilidad o la capacidad de escritura de las propiedades existentes y evita que se cambien los valores de las propiedades existentes. Además, congelar un objeto también impide que se cambie su prototipo. freeze() devuelve el mismo objeto que se pasó.
  110. ^ Daniel Friedman; William Byrd; Oleg Kiselyov; Jason Hemann (2018). El intrigante razonado, segunda edición . The MIT Press.
  111. ^ A. Casas, D. Cabeza, MV Hermenegildo. Un enfoque sintáctico para combinar notación funcional, evaluación diferida y orden superior en sistemas LP. 8º Simposio Internacional sobre Programación Funcional y Lógica (FLOPS'06), páginas 142-162, abril de 2006.
  112. ^ "Cómo hago mis cálculos". stallman.org . Consultado el 29 de abril de 2024 .
  113. ^ "Helix". helix-editor.com . Consultado el 29 de abril de 2024 .
  114. ^ Wakeling, David (2007). "Programación funcional en hojas de cálculo" (PDF) . Revista de programación funcional . 17 (1): 131–143. doi :10.1017/S0956796806006186. ISSN  0956-7968. S2CID  29429059.
  115. ^ Peyton Jones, Simon ; Burnett, Margaret ; Blackwell, Alan (marzo de 2003). "Mejora del lenguaje funcional más popular del mundo: funciones definidas por el usuario en Excel". Archivado desde el original el 16 de octubre de 2005.
  116. ^ Piro, Christopher (2009). Programación funcional en Facebook. CUFP 2009. Archivado desde el original el 17 de octubre de 2009. Consultado el 29 de agosto de 2009 .
  117. ^ "Sim-Diasca: un motor de simulación concurrente de eventos discretos a gran escala en Erlang". Noviembre de 2011.
  118. ^ 1 millón es así en 2011 Archivado el 19 de febrero de 2014 en Wayback Machine // Blog de WhatsApp, 6 de enero de 2012: "la última pieza importante de nuestra infraestructura es Erlang"
  119. ^ Momtahan, Lee (2009). Scala en EDF Trading: Implementación de un lenguaje específico de dominio para la fijación de precios de derivados con Scala. CUFP 2009. Archivado desde el original el 17 de octubre de 2009. Consultado el 29 de agosto de 2009 .
  120. ^ Graham, Paul (2003). "Superando los promedios" . Consultado el 29 de agosto de 2009 .
  121. ^ Sims, Steve (2006). Creación de una startup con ML estándar (PDF) . CUFP 2006. Consultado el 29 de agosto de 2009 .
  122. ^ Laurikari, Ville (2007). Programación funcional en seguridad de las comunicaciones. CUFP 2007. Archivado desde el original el 21 de diciembre de 2010. Consultado el 29 de agosto de 2009 .
  123. ^ Lorimer, RJ (19 de enero de 2009). "Se anuncia la aplicación Clojure para producción en vivo". InfoQ .
  124. ^ Bugnion, Pascal (2016). Scala para la ciencia de datos (1.ª ed.). Packt . ISBN 9781785281372.
  125. ^ "Por qué a los desarrolladores les gusta ClojureScript". StackShare . Consultado el 29 de abril de 2024 .
  126. ^ Herrick, Justin (29 de abril de 2024), jah2488/elm-companies , consultado el 29 de abril de 2024
  127. ^ "Por qué a los desarrolladores les gusta PureScript". StackShare . Consultado el 29 de abril de 2024 .
  128. ^ Equipo, Editorial (8 de enero de 2019). "ALLEGRO: todo lo que necesita saber sobre el mejor mercado en línea polaco". Noticias de comercio electrónico de Alemania . Consultado el 29 de abril de 2024 .
  129. ^ "Sitios web que utilizan Phoenix Framework - Wappalyzer". www.wappalyzer.com . Consultado el 29 de abril de 2024 .
  130. ^ "Programación funcional: 2019-2020". Departamento de Ciencias de la Computación de la Universidad de Oxford . Consultado el 28 de abril de 2020 .
  131. ^ "Programación I (Haskell)". Departamento de Informática del Imperial College de Londres . Consultado el 28 de abril de 2020 .
  132. ^ ab "Computer Science BSc - Modules" (Licenciatura en Ciencias de la Computación - Módulos) . Consultado el 28 de abril de 2020 .
  133. ^ ab Abelson, Hal ; Sussman, Gerald Jay (1985). "Prefacio a la segunda edición". Estructura e interpretación de programas informáticos (2.ª ed.). MIT Press.
  134. ^ John DeNero (otoño de 2019). "Computer Science 61A, Berkeley". Departamento de Ingeniería Eléctrica y Ciencias de la Computación, Berkeley . Consultado el 14 de agosto de 2020 .
  135. ^ Emmanuel Schanzer de Bootstrap entrevistado en el programa de televisión Triangulation de la cadena TWiT.tv
  136. ^ "¿Por qué Scheme para la programación introductoria?". home.adelphi.edu . Consultado el 29 de abril de 2024 .
  137. ^ Personal, IMACS (3 de junio de 2011). "¿Qué es Scheme y por qué es beneficioso para los estudiantes?". IMACS: cómo formar mejores pensadores para la vida . Consultado el 29 de abril de 2024 .

Lectura adicional

  • Abelson, Hal ; Sussman, Gerald Jay (1985). Estructura e interpretación de programas informáticos. MIT Press.
  • Cousineau, Guy y Michel Mauny. El enfoque funcional de la programación . Cambridge, Reino Unido: Cambridge University Press , 1998.
  • Curry, Haskell Brooks y Feys, Robert y Craig, William. Combinatory Logic . Volumen I. North-Holland Publishing Company, Ámsterdam, 1958.
  • Curry, Haskell B. ; Hindley, J. Roger ; Seldin, Jonathan P. (1972). Combinatory Logic . Vol. II. Ámsterdam: Holanda Septentrional. ISBN 978-0-7204-2208-5.
  • Dominus, Mark Jason. Perl de orden superior . Morgan Kaufmann . 2005.
  • Felleisen, Matthias; Findler, Robert; Flatt, Matthew; Krishnamurthi, Shriram (2018). Cómo diseñar programas. MIT Press.
  • Graham, Paul. ANSI Common LISP . Englewood Cliffs, Nueva Jersey: Prentice Hall , 1996.
  • MacLennan, Bruce J. Programación funcional: práctica y teoría . Addison-Wesley, 1990.
  • Michaelson, Greg (10 de abril de 2013). Introducción a la programación funcional a través del cálculo lambda . Courier Corporation. ISBN 978-0-486-28029-5.
  • O'Sullivan, Brian; Stewart, Don; Goerzen, John (2008). Haskell en el mundo real. O'Reilly.
  • Pratt, Terrence W. y Marvin Victor Zelkowitz . Lenguajes de programación: diseño e implementación . 3.ª ed. Englewood Cliffs, Nueva Jersey: Prentice Hall , 1996.
  • Salus, Peter H. Lenguajes de programación funcional y lógica . Vol. 4 del Manual de lenguajes de programación. Indianápolis, Indiana: Macmillan Technical Publishing, 1998.
  • Thompson, Simon. Haskell: El arte de la programación funcional . Harlow, Inglaterra: Addison-Wesley Longman Limited, 1996.
Escuche este artículo ( 28 minutos )
Icono de Wikipedia hablado
Este archivo de audio se creó a partir de una revisión de este artículo con fecha del 25 de agosto de 2011 y no refleja ediciones posteriores. ( 25 de agosto de 2011 )
  • Ford, Neal. «Pensamiento funcional» . Consultado el 10 de noviembre de 2021 .
  • Akhmechet, Slava (19 de junio de 2006). «defmacro: programación funcional para el resto de nosotros» . Consultado el 24 de febrero de 2013 .Una introducción
  • Programación funcional en Python (por David Mertz): parte 1, parte 2, parte 3
Obtenido de "https://es.wikipedia.org/w/index.php?title=Programación_funcional&oldid=1253334916"