Mientras más programación funcional hago, más me parece que agrega una capa adicional de abstracción que parece como la capa de una cebolla, que abarca todas las capas anteriores.
No sé si esto es cierto, así que, dejando de lado los principios de OOP con los que he trabajado durante años, ¿alguien puede explicar qué tan funcional representa o no con precisión alguno de ellos: encapsulación, abstracción, herencia, polimorfismo?
Creo que todos podemos decir, sí, tiene encapsulación a través de tuplas, o las tuplas cuentan técnicamente como un hecho de "programación funcional" o ¿son solo una utilidad del lenguaje?
Sé que Haskell puede cumplir con el requisito de "interfaces", pero de nuevo, ¿no está seguro si su método es funcional? Supongo que el hecho de que los functores tienen una base matemática podría decirse que son una construcción definitiva con la expectativa de ser funcional, ¿tal vez?
Por favor, detalle cómo cree que funcional cumple o no los 4 principios de OOP.
Editar: entiendo muy bien las diferencias entre el paradigma funcional y el paradigma orientado a objetos y me doy cuenta de que hay muchos lenguajes multiparadigm en estos días que pueden hacer ambas cosas. Realmente solo estoy buscando definiciones de cómo fp (piense purista, como Haskell) puede hacer cualquiera de las 4 cosas enumeradas, o por qué no puede hacer ninguna de ellas. es decir, "La encapsulación se puede hacer con cierres" (o si estoy equivocado en esta creencia, indique por qué).
fuente
Respuestas:
La programación funcional no es una capa por encima de OOP; Es un paradigma completamente diferente. Es posible hacer OOP en un estilo funcional (F # fue escrito exactamente para este propósito), y en el otro extremo del espectro tienes cosas como Haskell, que rechaza explícitamente los principios de orientación a objetos.
Puede realizar la encapsulación y la abstracción en cualquier lenguaje lo suficientemente avanzado como para admitir módulos y funciones. OO proporciona mecanismos especiales para la encapsulación, pero no es algo inherente a OO. El punto de OO es el segundo par que mencionaste: herencia y polimorfismo. El concepto se conoce formalmente como sustitución de Liskov, y no se puede obtener sin el soporte de nivel de lenguaje para la programación orientada a objetos. (Sí, es posible fingirlo en algunos casos, pero pierde muchas de las ventajas que OO aporta).
La programación funcional no se centra en la sustitución de Liskov. Se enfoca en aumentar el nivel de abstracción y en minimizar el uso de estado mutable y rutinas con "efectos secundarios", que es un término que a los programadores funcionales les gusta usar para hacer que las rutinas que realmente hacen algo (en lugar de simplemente calcular algo) suenen de miedo. Pero, de nuevo, son paradigmas completamente separados, que se pueden usar juntos o no, dependiendo del lenguaje y la habilidad del programador.
fuente
La siguiente intuición me parece útil para comparar OOP y FP.
En lugar de considerar FP como un superconjunto de OOP, piense en OOP y FP como dos formas alternativas de mirar un modelo de cálculo subyacente similar en el que tiene:
En OOP esto es capturado por
En FP esto es capturado por
Con esta interpretación, un objeto puede verse como una colección de cierres (sus métodos) que capturan todas las mismas variables no locales (las variables miembro del objeto son comunes a todos los cierres de la colección). Esta vista también está respaldada por el hecho de que, en lenguajes orientados a objetos, los cierres a menudo se modelan como objetos con exactamente un método.
Creo que los diferentes puntos de vista se originan en el hecho de que la vista orientada a objetos se centra en los objetos (los datos) mientras que la vista funcional se centra en las funciones / cierres (las operaciones).
fuente
Depende de a quién le pidas una definición de POO. Pregúntele a cinco personas y probablemente obtendrá seis definiciones. Wikipedia dice :
Entonces, cuando alguien dé una respuesta muy definitiva, tómela con un grano de sal.
Dicho esto, hay un buen argumento para argumentar que sí, FP es un superconjunto de OOP como paradigma. En particular, la definición de Alan Kay del término programación orientada a objetos no contradice esta noción (pero la de Kristen Nygaard sí ). Todo lo que le preocupaba a Kay era que todo es un objeto, y que la lógica se implementa al pasar mensajes entre objetos.
Quizás lo más interesante para su pregunta es que las clases y los objetos pueden considerarse en términos de funciones y cierres devueltos por funciones (que actúan como clases y constructores a la vez). Esto se acerca mucho a la programación basada en prototipos, y de hecho JavaScript permite hacer precisamente eso.
(Por supuesto, JavaScript permite la mutación de valores que es ilegal en la programación puramente funcional, pero tampoco se requiere en una definición estricta de OOP).
Sin embargo, la pregunta más importante es: ¿Es esta una clasificación significativa de OOP? ¿Es útil pensar en él como un subconjunto de programación funcional? Creo que en la mayoría de los casos, no lo es.
fuente
FP como OO no es un término bien definido. Hay escuelas con definiciones diferentes, a veces conflictivas. Si toma lo que tienen en común, se reduce a:
programación funcional es programación con funciones de primera clase
La programación OO es la programación con polimorfismo de inclusión combinado con al menos una forma restringida de sobrecarga resuelta dinámicamente. (Una nota al margen: en los círculos OO, el polimorfismo generalmente se considera polimorfismo de inclusión , mientras que las escuelas FP generalmente significa polimorfismo paramétrico ).
Todo lo demás está presente en otro lugar o ausente en algunos casos.
FP y OO son dos herramientas de construcción de abstracciones. Cada uno tiene sus propias fortalezas y debilidades (por ejemplo, tienen una dirección de extensión preferida diferente en el problema de expresión), pero ninguna es intrínsecamente más poderosa que la otra. Puede construir un sistema OO sobre un núcleo FP (CLOS es uno de esos sistemas). Puede usar un marco OO para obtener funciones de primera clase (vea la forma en que las funciones lambda se definen en C ++ 11, por ejemplo).
fuente
std::function
, a la que se pueden asignar tanto punteros de función como lambdas, es decididamente genérico, no orientado a objetos. Esto no es sorprendente, porque la marca limitada de polimorfismo de la orientación a objetos (polimorfismo de subtipo) es estrictamente menos poderosa que el polimorfismo paramétrico (incluso Hindley-Milner, y mucho menos el Sistema F-omega completo).No; OOP puede verse como un superconjunto de programación procesal y difiere fundamentalmente del paradigma funcional porque tiene un estado representado en los campos de instancia. En el paradigma funcional, las variables son funciones que se aplican sobre los datos constantes para obtener el resultado deseado.
En realidad, puede considerar la programación funcional como un subconjunto de OOP; Si hace que todas sus clases sean inmutables, puede considerar que tiene algún tipo de programación funcional.
fuente
Responder:
Wikipedia tiene un excelente artículo sobre programación funcional con algunos de los ejemplos que solicita. @Konrad Rudolph ya proporcionó el enlace al artículo de OOP .
No creo que un paradigma sea un superconjunto del otro. Son diferentes perspectivas sobre la programación y algunos problemas se resuelven mejor desde una perspectiva y otros desde otra.
Su pregunta se complica aún más por todas las implementaciones de FP y OOP. Cada idioma tiene sus propias peculiaridades que son relevantes para cualquier buena respuesta a su pregunta.
Divagación cada vez más tangencial:
Me gusta la idea de que un lenguaje como Scala intente darte lo mejor de ambos mundos. Me preocupa que también te dé las complicaciones de ambos mundos.
Java es un lenguaje OO, pero la versión 7 agregó una función de "prueba con recursos" que puede usarse para imitar una especie de cierre. Aquí imita la actualización de una variable local "a" en el medio de otra función, sin que sea visible para esa función. En este caso, la primera mitad de la otra función es el constructor Closure Try () y la segunda mitad es el método close ().
Salida:
Esto podría ser útil para su propósito de abrir una secuencia, escribir en la secuencia y cerrarla de manera confiable, o simplemente para emparejar dos funciones de una manera que no se olvide de llamar a la segunda después de hacer un trabajo entre ellas. . Por supuesto, es tan nuevo e inusual que otro programador podría eliminar el bloque de prueba sin darse cuenta de que está rompiendo algo, por lo que actualmente es una especie de antipatrón, pero es interesante que se pueda hacer.
Puede expresar cualquier bucle en la mayoría de los idiomas imperativos como una recursividad. Los objetos y las variables pueden hacerse inmutables. Se pueden escribir procedimientos para minimizar los efectos secundarios (aunque yo diría que una verdadera función no es posible en una computadora: el tiempo que lleva ejecutar y los recursos del procesador / disco / sistema que consume son efectos secundarios inevitables). Se puede hacer que algunos lenguajes funcionales también realicen muchas, si no todas, las operaciones orientadas a objetos. No tienen que ser mutuamente excluyentes, aunque algunos lenguajes tienen limitaciones (como no permitir ninguna actualización de variables) que impiden ciertos patrones (como los campos mutables).
Para mí, las partes más útiles de la programación orientada a objetos son la ocultación de datos (encapsulación), el tratamiento de objetos suficientemente similares como el mismo (polimorfismo) y la recopilación de sus datos y métodos que operan en esos datos juntos (objetos / clases). La herencia puede ser el buque insignia de OOP, pero para mí es la parte menos importante y menos utilizada.
Las partes más útiles de la programación funcional son la inmutabilidad (tokens / valores en lugar de variables), funciones (sin efectos secundarios) y cierres.
No creo que esté orientado a objetos, pero tengo que decir que una de las cosas más útiles en informática es la capacidad de declarar una interfaz, luego tener varias piezas de funcionalidad y datos para implementar esa interfaz. También me gusta tener algunos datos mutables con los que trabajar, así que supongo que no me siento totalmente cómodo en lenguajes exclusivamente funcionales, aunque trato de limitar la mutabilidad y los efectos secundarios en todos los diseños de mis programas.
fuente