Usando generadores y lambda, podemos hacer programación funcional con Python. También puedes lograr lo mismo con Ruby.
Entonces la pregunta es: ¿por qué necesitamos lenguajes de programación funcionales específicos como Erlang, Haskell y Scheme? ¿Hay algo diferente que proporcionan estos lenguajes de programación funcionales específicos? ¿Por qué no podemos usar Python para la programación funcional?
programming-languages
python
functional-programming
Joshua Partogi
fuente
fuente
Respuestas:
Aprecio la pregunta, porque personalmente soy un gran admirador tanto de Python como del estilo funcional de programación. Tengo una larga experiencia en Python y comencé a aprender Haskell recientemente, así que aquí hay algunos puntos basados en mis experiencias personales sobre las diferencias entre estos lenguajes, desde una perspectiva funcional.
Pureza
Incluso si no le importa la pureza de las funciones (es decir, no tener efectos secundarios) como un principio, tiene un efecto práctico sobre lo fácil que es leer el código y razonar al respecto. Incluso si mantiene la pureza en sus propias funciones de Python, existe una gran diferencia en hacer que el compilador haga cumplir la pureza y, sobre todo, en tener la biblioteca estándar construida en términos de pureza y estructuras de datos inmutables.
Actuación
Puede que le interese o no el rendimiento dependiendo del dominio de su aplicación, pero la escritura estática y la pureza garantizada le dan al compilador mucho más para trabajar, en comparación con Python y otros lenguajes dinámicos (aunque tengo que admitir que PyPy está haciendo un gran trabajo) incursiones, y por ejemplo, LuaJIT raya en lo milagroso).
Optimización de llamadas de cola
Relacionado con el rendimiento, pero ligeramente diferente. Incluso si no le importa demasiado el rendimiento en tiempo de ejecución, no tener una optimización de llamada de cola (especialmente para la recursividad de cola) limita las formas en que puede implementar algoritmos en Python sin alcanzar los límites de pila.
Sintaxis
Esta es la razón principal por la que comencé a mirar lenguajes funcionales "reales" en lugar de usar Python con un estilo funcional. Aunque creo que Python tiene una sintaxis muy expresiva en general, tiene algunos puntos débiles específicos de la codificación funcional. Por ejemplo:
f = g . h
vs.f = lambda *arg: g(h(*arg))
f = map g
vs.f = functools.partial(map, g)
sum = reduce (+) lst
vs.sum = reduce(operator.add, lst)
y = func1 $ func2 $ func3 x
más fácil de leer quey = func1(func2(func3(x)))
, una vez que esté familiarizado con esa notación.fuente
Estas son las diferencias más importantes:
Haskell
Haskell y Erlang
Erlang
Esquema
Todos los idiomas
Además, debe echar un vistazo a los idiomas de la familia ML como SML, Ocaml y F # y Scala, que fusiona OO y la programación funcional de una manera nueva. Todos estos idiomas tienen características únicas e interesantes.
fuente
Es difícil definir exactamente qué es un "lenguaje funcional": de los idiomas que enumeró, solo Haskell es puramente funcional (todos los demás adoptan algún tipo de enfoque híbrido). Sin embargo, hay ciertas características de lenguaje que son muy útiles para la programación funcional, y Ruby y Python no tienen suficientes para ser entornos muy buenos para FP. Aquí está mi lista de verificación personal, en orden de importancia:
La necesidad de (1) debería ser obvia: las funciones de orden superior son extremadamente difíciles sin funciones de primera clase. Cuando la gente habla de que Ruby y Python son buenos lenguajes para FP, generalmente hablan de esto. Sin embargo, esta característica particular es necesaria pero no suficiente para hacer que un lenguaje sea bueno para FP.
(2) ha sido una necesidad tradicional para FP desde que se inventó el Scheme. Sin TCO, es imposible programar con una recursión profunda, que es una de las piedras angulares de FP, porque se producen desbordamientos de pila. El único lenguaje "funcional" (por definición popular) que no tiene esto es Clojure (debido a las limitaciones de la JVM), pero Clojure tiene una variedad de hacks para simular el TCO. (Para su información, Ruby TCO es específico de la implementación , pero Python específicamente no lo admite ). La razón por la que debe garantizarse el TCO es que si es específica de la implementación, las funciones recursivas profundas se romperán con algunas implementaciones, por lo que no puede realmente úsalos en absoluto.
(3) es otra gran cosa que los lenguajes funcionales modernos (especialmente Haskell, Erlang, Clojure y Scala) tienen que Ruby y Python no tienen. Sin entrar en demasiados detalles, la inmutabilidad garantizada elimina clases enteras de errores, especialmente en situaciones concurrentes, y permite cosas claras como estructuras de datos persistentes . Es muy difícil aprovechar estos beneficios sin soporte de nivel de idioma.
(4) es, para mí, lo más interesante de los lenguajes puramente funcionales (a diferencia de los lenguajes híbridos). Considere la siguiente función de Ruby extremadamente simple:
Esto parece una función pura, pero debido a la sobrecarga del operador, podría mutar cualquiera de los parámetros o causar efectos secundarios como imprimir en la consola. Es poco probable que alguien sobrecargue al
+
operador para tener un efecto secundario, pero el lenguaje no ofrece garantías. (Lo mismo se aplica a Python, aunque tal vez no con este ejemplo específico).En un lenguaje puramente funcional, por otro lado, existen garantías a nivel de lenguaje de que las funciones son referencialmente transparentes. Esto tiene numerosas ventajas: las funciones puras se pueden memorizar fácilmente; se pueden probar fácilmente sin depender de ningún tipo de estado global; y los valores dentro de la función pueden evaluarse perezosamente o en paralelo sin preocuparse por los problemas de concurrencia. Haskell aprovecha al máximo esto, pero no sé lo suficiente sobre otros lenguajes funcionales para saber si lo hacen.
Dicho todo esto, es posible utilizar técnicas de FP en casi cualquier lenguaje (incluso Java). Por ejemplo, MapReduce de Google está inspirado en ideas funcionales, pero que yo sepa, no usan ningún lenguaje "funcional" para sus grandes proyectos (creo que usan principalmente C ++, Java y Python).
fuente
Los idiomas que mencionas son muy diferentes.
Mientras Python y Ruby son lenguajes de escritura dinámica, Haskell está estáticamente escrita. Erlang es un idioma concurrente y utiliza el modelo de actor y es muy diferente de todos los demás idiomas que menciona.
Python y Ruby tienen muchas construcciones imperativas, mientras que en un lenguaje funcional más puro como Haskell, todo devuelve algo o, en otras palabras, todo es una función.
fuente
Tarde a la fiesta como siempre, pero de todas maneras voy a decir cosas.
Un lenguaje de programación funcional no es un lenguaje que permita la programación funcional. Si tuviéramos que seguir esa definición, casi cualquier lenguaje en cualquier lugar es un lenguaje de programación funcional. (Lo mismo se aplica a OOP, por cierto. Puede escribir en un estilo OOP en C si lo desea. Por lo tanto, de acuerdo con su lógica, C es un lenguaje OOP).
Lo que hace que un lenguaje de programación funcional no sea lo que le permite programar, es lo que le permite programar fácilmente . Esa es la clave.
Por lo tanto, Python tiene lambdas (que son asuntos increíblemente anémicos) y le brinda un par de funciones de biblioteca que verá en bibliotecas funcionales, así como "mapa" y "pliegue". Sin embargo, esto no es suficiente para convertirlo en un lenguaje de programación funcional, porque es difícil o imposible programar consistentemente en un estilo funcional adecuado (¡y el lenguaje ciertamente no aplica este estilo!). En esencia, Python es un lenguaje imperativo relacionado con las operaciones de manipulación de estado y estado y esto simplemente está en desacuerdo con la expresión y la semántica de evaluación de expresiones de un lenguaje funcional.
Entonces, ¿por qué tenemos lenguajes de programación funcionales cuando Python (o Ruby (o inserte el lenguaje de su elección)) puede "hacer programación funcional"? Porque Python, et al no pueden hacer una programación funcional adecuada. Es por eso.
fuente
Usted puede hacer la programación funcional en Java (véase, por ejemplo http://functionaljava.org/ ). También se puede hacer la programación orientada a objetos en C . Simplemente no es tan idiomático.
Entonces, de hecho, no necesitamos absolutamente Erlang, Haskell, Scheme o ningún lenguaje de programación específico, pero todos representan diferentes enfoques y diferentes compensaciones, lo que hace que algunas tareas sean más fáciles y más difíciles. Lo que debe usar depende de lo que quiera lograr.
fuente
Esta pregunta puede aplicarse a un número infinito de lenguajes y paradigmas.
La mayoría, si no todos los idiomas existen por una razón específica. Existen porque alguien tenía una necesidad de que no se llenara el idioma actual, o que se llenara mal. (Por supuesto, esto no se aplica a todos los idiomas, pero creo que se aplica a la mayoría de los idiomas conocidos). Por ejemplo, python se desarrolló originalmente para interactuar con Amoeba OS [ 1 , 2 ] y Erlang se creó para ayudar en el desarrollo de aplicaciones de telefonía [ 3 ]. Entonces, una respuesta a la pregunta "¿Por qué necesitamos otro lenguaje funcional?" simplemente puede ser porque a [insert-name-of-someone-who-know-how-to-design-languages] no le gustó la forma en que Python lo hizo.
Eso resume bastante bien lo que creo que es la respuesta. Si bien puedes hacer cualquier cosa con Python que puedas hacer con un lenguaje funcional, ¿realmente quieres hacerlo? Todo lo que puedes hacer en C, puedes hacerlo en ensamblaje, pero ¿te gustaría hacerlo? Diferentes idiomas siempre serán mejores para hacer cosas diferentes, y así es como debe ser.
fuente
La programación funcional se trata tanto de un paradigma de diseño como de características específicas del lenguaje. O, dicho de otro modo, lambdas y una función de mapa no hacen un lenguaje de programación funcional. Python y Ruby tienen algunas características inspiradas en lenguajes de programación funcionales, pero aún así generalmente escribes código de una manera muy imperativa. (Es algo así como C: puede escribir código similar a OO en C, pero nadie considera seriamente que C sea un lenguaje OO).
Mire: la programación funcional no se trata solo de lambdas, o
map
funciones de orden superior. Se trata de diseño . Un programa escrito en un lenguaje de programación funcional "verdadero" resuelve problemas mediante la composición de funciones. Si bien los programas escritos en Ruby o Python pueden usar características similares a FP, generalmente no se leen como un conjunto de funciones compuestas.fuente
Cada lenguaje funcional que mencionó encaja bastante bien en cierto nicho y los patrones idiomáticos que cada uno fomenta los hace muy adecuados para ciertas tareas que serían imposibles de lograr en Python a menos que haya construido una gran biblioteca de módulos auxiliares. El más obvio de uno de esos nichos de excelencia es el modelo de concurrencia de Erlang. Los otros también tienen fortalezas similares.
fuente
Todos los conceptos disponibles en lambda-calculus, LISP y Scheme están disponibles en Python, por lo que sí, puedes hacer programación funcional en él. Si es conveniente o no, es una cuestión de contexto y gusto.
Puede escribir fácilmente un intérprete LISP (u otro lenguaje funcional) en Python (Ruby, Scala) (¿qué significa eso?). Puede escribir un intérprete para Python utilizando funciones puramente funcionales, pero tomaría mucho trabajo. Incluso los lenguajes "funcionales" son multi-paradigma hoy en día.
Este viejo y hermoso libro tiene la mayoría (aunque no todas) las respuestas sobre cuál es la esencia de la programación funcional.
fuente
eval()
función, que es necesaria para que el código sea datos , pero va más allá: le permite modificar la mayor parte del entorno de tiempo de ejecución, como en LISP.eval()
son una metaprogramación en tiempo de ejecución. A veces es útil, pero es extremadamente costoso. Las macros de Lisp son diferentes, es una metaprogramación en tiempo de compilación. No está disponible en Python en ninguna forma utilizable.Porque Python también puede programar en un estilo no funcional, y eso no es lo suficientemente bueno para el purista de FP. Sin embargo, los programadores más pragmáticos pueden disfrutar de los beneficios del estilo funcional sin ser dogmáticos al respecto:
- John Hughes, ¿Por qué es importante la programación funcional?
fuente
goto
es terrible.call-with-current-continuation
.