He leído algunos textos sobre programación declarativa / funcional (lenguajes), probé Haskell y también escribí uno. Por lo que he visto, la programación funcional tiene varias ventajas sobre el estilo imperativo clásico:
- Programas apátridas; Sin efectos secundarios
- Concurrencia; Juega extremadamente bien con la creciente tecnología de múltiples núcleos
- Los programas suelen ser más cortos y, en algunos casos, más fáciles de leer.
La productividad aumenta (ejemplo: Erlang)
La programación imperativa es un paradigma muy antiguo (que yo sepa) y posiblemente no sea adecuado para el siglo XXI.
¿Por qué las empresas que usan o los programas escritos en lenguajes funcionales siguen siendo tan "raros"?
¿Por qué, cuando observamos las ventajas de la programación funcional, seguimos usando lenguajes de programación imperativos?
Tal vez fue demasiado temprano para eso en 1990, ¿pero hoy?
functional-programming
pankrax
fuente
fuente
Respuestas:
Porque todas esas ventajas también son desventajas.
Los programas del mundo real tienen que ver con los efectos secundarios y la mutación. Cuando el usuario presiona un botón es porque quiere que algo suceda. Cuando escriben algo, quieren que ese estado reemplace cualquier estado que solía estar allí. Cuando Jane Smith en contabilidad se casa y cambia su nombre a Jane Jones, es mejor que la base de datos que respalda el proceso comercial que imprime su cheque de pago se trata de manejar ese tipo de mutación. Cuando disparas la ametralladora al alienígena, la mayoría de las personas no modelan mentalmente eso como la construcción de un nuevo alienígena con menos puntos de vida; modelan eso como una mutación de las propiedades de un extraterrestre existente.
Cuando los conceptos del lenguaje de programación funcionan fundamentalmente contra el dominio que se está modelando, es difícil justificar el uso de ese lenguaje.
El problema simplemente se resuelve. Con estructuras de datos inmutables, tiene una seguridad de subprocesos barata a costa de posiblemente trabajar con datos obsoletos. Con estructuras de datos mutables, tiene la ventaja de trabajar siempre en datos nuevos a costa de tener que escribir una lógica complicada para mantener los datos consistentes. No es que uno de esos sea obviamente mejor que el otro.
Excepto en los casos en que son más largos y difíciles de leer. Aprender a leer programas escritos en un estilo funcional es una habilidad difícil; la gente parece ser mucho mejor para concebir los programas como una serie de pasos a seguir, como una receta, más que como una serie de cálculos a realizar.
La productividad tiene que subir mucho para justificar el gasto masivo de contratar programadores que saben programar en un estilo funcional.
Y recuerde, no desea tirar un sistema de trabajo; la mayoría de los programadores no están construyendo nuevos sistemas desde cero, sino que mantienen los sistemas existentes, la mayoría de los cuales fueron construidos en lenguajes no funcionales. Imagínese tratando de justificar eso a los accionistas. ¿Por qué descartó su sistema de nómina de trabajo existente para construir uno nuevo a costa de millones de dólares? "Porque la programación funcional es increíble" es poco probable que deleite a los accionistas.
La programación funcional también es muy antigua. No veo cómo la edad del concepto es relevante.
No me malinterpretes. Me encanta la programación funcional, me uní a este equipo porque quería ayudar a traer conceptos de la programación funcional a C #, y creo que programar en un estilo inmutable es el camino hacia el futuro. Pero la programación en un estilo funcional tiene enormes costos que no se pueden descartar. El cambio hacia un estilo más funcional va a suceder lenta y gradualmente durante décadas. Y eso es lo que será: un cambio hacia un estilo más funcional, no una aceptación general de la pureza y belleza de Haskell y el abandono de C ++.
Construyo compiladores para vivir y definitivamente estamos adoptando un estilo funcional para la próxima generación de herramientas de compilación. Esto se debe a que la programación funcional es fundamentalmente una buena combinación para el tipo de problemas que enfrentamos. Nuestros problemas tienen que ver con tomar información en bruto (cadenas y metadatos) y transformarlos en diferentes cadenas y metadatos. En situaciones en las que ocurren mutaciones, como si alguien estuviera escribiendo en el IDE, el espacio del problema se presta inherentemente a técnicas funcionales como la reconstrucción incremental solo de las partes del árbol que cambiaron. Muchos dominios no tienen estas buenas propiedades que los hacen evidentemente susceptibles a un estilo funcional .
fuente
Mentes maestras de la programación: conversaciones con los creadores de los principales lenguajes de programación
fuente
La respuesta común es que ninguno de los dos debería reemplazar al otro: son herramientas diferentes que tienen diferentes conjuntos de pros y contras, y qué enfoque tiene la ventaja diferirá según el proyecto y otros problemas "blandos" como el grupo de talentos disponible.
Creo que tiene razón en que el crecimiento de la concurrencia debido a múltiples núcleos aumentará el porcentaje (del conjunto global de proyectos de desarrollo) cuando se elige la programación funcional sobre otros estilos.
Creo que es raro hoy porque la mayoría del grupo de talentos profesionales de hoy se siente más cómodo con tecnologías imperativas y orientadas a objetos. Por ejemplo, más de una vez elegí Java como lenguaje para un proyecto comercial porque era lo suficientemente bueno, no controvertido, y sé que nunca me quedaré sin personas que puedan programar (lo suficientemente bien) en él.
fuente
A pesar de las ventajas de la programación funcional, la programación imperativa y orientada a objetos nunca desaparecerá por completo.
La programación imperativa y orientada a objetos es una descripción paso a paso del problema y su solución. Como tal, puede ser más fácil de comprender. La programación funcional puede ser un poco oscura.
En última instancia, un programa útil siempre tendrá efectos secundarios (como proporcionar una salida real al usuario para el consumo), por lo que los lenguajes funcionales más puros aún necesitarán una forma de ingresar al mundo imperativo de vez en cuando.
El estado actual de la técnica es que los lenguajes imperativos (como C #) toman prestadas características del mundo funcional (como las declaraciones lambda) y viceversa.
fuente
¿No es así?
Smalltalk fue un gran sistema orientado a objetos en el pasado. ¿Por qué no se ha hecho cargo de la programación orientada a objetos? Pues sí. Simplemente no se parece a Smalltalk. Los lenguajes principales se vuelven cada vez más parecidos a Smalltalk con C ++, Java, C #, etc. La moda y el estilo cambian más lentamente que nada, por lo que cuando OO se generalizó, lo conseguimos pegando partes de OO a idiomas antiguos para que pareciera lo suficiente como para tragar C .
Funcional es de la misma manera. Haskell era un gran lenguaje funcional. Pero hoy tenemos más masa de programadores que usan sintaxis tipo C que hace 20 años. Por lo tanto, debe parecerse a C. Hecho: observe cualquier expresión de LINQ y dígame que no es funcional.
fuente
dynamic
. Esa es la más pequeña de estas características, por lo que no me sorprende que solo esté presente en la última versión del más moderno de estos tres idiomas. :-)Creo que los idiomas imperativos son más frecuentes simplemente porque a eso están acostumbrados más personas. Ni la programación funcional ni el modelo de programación imperativo son más oscuros o académicos que el otro. De hecho, son complementos.
Un cartel decía que el código imperativo es más fácil de entender que el código de programación funcional. Esto solo es cierto si el lector ya ha visto el código imperativo, especialmente si los ejemplos anteriores son parte de la misma "familia" (por ejemplo, C / C ++, Perl, PHP y Java). No diría que es cierto para cualquier lenguaje imperativo; tome una comparación de Java y Forth, para hacer un ejemplo extremo.
Para un laico, todos los lenguajes de programación son galimatías indescifrables, excepto quizás los lenguajes detallados como Hypertalk y SQL. (Cabe destacar que SQL es un lenguaje declarativo y / o funcional y goza de una enorme popularidad).
Si hubiéramos sido entrenados inicialmente en un lenguaje Lisp-y o Haskell-y desde el principio, todos pensaríamos que los lenguajes de programación funcionales son perfectamente normales.
fuente
Ya has recibido suficientes respuestas que mencionaré solo un par de cosas que aún no veo mencionadas.
Primero y (en mi opinión) lo más importante, los lenguajes de procedimiento se han beneficiado enormemente de su grado de coincidencia. Por ejemplo, casi cualquier persona que conozca casi todos los lenguajes de procedimiento (u OO) convencionales en casi cualquier grado puede leer la mayoría de los demás razonablemente bien. Evito activamente trabajar en Java, C #, Cobol, Fortran o Basic (por solo algunos ejemplos), pero puedo leer cualquiera de ellos razonablemente bien, de hecho, casi tan bien como las personas que los usan todos los días.
En el lado funcional, eso es mucho menos cierto. Solo por ejemplo, también puedo escribir Scheme de manera bastante razonable, pero eso es de poca utilidad para leer Ocaml o Haskell (solo por un par de ejemplos). Incluso dentro de una sola familia (p. Ej., Scheme vs., Common Lisp) la familiaridad con uno no parece traducirse tan bien al otro.
La afirmación de que el código funcional es más legible tiende a ser verdad solo bajo un rango estrecho de condiciones. Para las personas que están extremadamente familiarizadas con el lenguaje, la legibilidad es realmente excelente, pero para todos los demás, a menudo es casi inexistente. Peor aún, si bien las diferencias en los lenguajes de procedimiento son en gran medida de sintaxis y, por lo tanto, se aprenden con relativa facilidad, las diferencias en los lenguajes funcionales a menudo son mucho más fundamentales, por lo que requieren un estudio considerable para comprender realmente (por ejemplo, saber que Lisp es de poca ayuda para comprender a las mónadas).
El otro punto importante es que la idea de que los programas funcionales son más cortos que los de procedimiento a menudo se basa más en la sintaxis que en la semántica. Los programas escritos en Haskell (por ejemplo) son a menudo bastante cortos, pero su funcionalidad es una parte bastante pequeña de eso. Una gran oferta si es simplemente que Haskell tiene una sintaxis relativamente breve.
Pocos lenguajes puramente funcionales pueden competir bien con APL por el código fuente conciso (aunque, para ser justos, APL también admite la creación de funciones de nivel superior, por lo que esa no es una gran diferencia como en otros casos). Por el contrario, Ada y C ++ (solo para un par de ejemplos) pueden ser bastante competitivos en términos del número de operaciones necesarias para realizar una tarea determinada, pero la sintaxis es (al menos generalmente) sustancialmente más detallada.
fuente
Sin necesidad percibida
Recuerdo la respuesta de mi viejo jefe Rick Cline cuando le mostré una copia de la conferencia del Premio Turing de John Backus titulada ¿Se puede liberar la programación del estilo von Neumann?
Su respuesta: "¡Quizás algunos de nosotros no queremos ser liberados del estilo von Neumann!"
fuente
Funcional es mejor para algunas cosas y peor para otras, por lo que nunca "se hará cargo". Sin embargo, ya es omnipresente en el mundo real.
Los programas sin estado son más fáciles de probar. Esto ahora es muy apreciado y a menudo explotado en la industria.
Estás combinando concurrencia y paralelismo.
La concurrencia se puede hacer de manera efectiva utilizando procesos secuenciales de comunicación (CSP). El código dentro de un CSP puede mutar su estado local, pero los mensajes enviados entre ellos siempre deben ser inmutables.
La programación puramente funcional juega muy mal con el multinúcleo porque es muy poco amigable con el caché. Los núcleos terminan compitiendo por la memoria compartida y los programas paralelos no escalan.
Scala a menudo se considera un lenguaje funcional, pero no es más funcional que C #, que es uno de los lenguajes más populares en el mundo de hoy.
La programación puramente funcional tiene muchas desventajas serias, por lo que utilizamos lenguajes funcionales impuros como Lisp, Scheme, SML, OCaml, Scala y C #.
fuente
Cuando pienso en lo que la programación funcional podría aportar a mis proyectos en el trabajo, siempre me guían por el mismo camino de pensamiento:
Para obtener todas las ventajas de la programación funcional, necesita pereza. Sí, hay lenguajes funcionales estrictos, pero los beneficios reales de la programación funcional no brillan tan bien en un código estricto. Por ejemplo, en Haskell es fácil crear una secuencia de operaciones diferidas en una lista y concatenarlas y aplicarlas a una lista. P.ej.
op1 $ op2 $ op3 $ op4 $ someList
. Sé que no va a construir la lista completa e internamente solo voy a obtener un buen ciclo que recorre los elementos uno por uno. Esto le permite escribir código realmente modular. La interfaz entre dos módulos puede implicar la entrega de estructuras de datos potencialmente vastas y, sin embargo, no es necesario que la estructura resida.Pero cuando tienes pereza, se vuelve difícil razonar sobre el uso de la memoria. Cambiar los indicadores del compilador de Haskell con frecuencia cambia la cantidad de memoria utilizada por un algoritmo de O (N) a O (1), excepto que a veces no lo hace. Esto no es realmente aceptable cuando tiene aplicaciones que necesitan aprovechar al máximo toda la memoria disponible, y no es excelente incluso para aplicaciones que no necesitan toda la memoria.
fuente
Dos cosas:
fuente