La mayoría de los lenguajes principales, incluidos los lenguajes de programación orientada a objetos (OOP) como C #, Visual Basic, C ++ y Java, fueron diseñados para soportar principalmente la programación imperativa (de procedimiento), mientras que los lenguajes similares a Haskell / gofer son puramente funcionales. ¿Alguien puede explicar cuál es la diferencia entre estas dos formas de programación?
Sé que depende de los requisitos del usuario elegir la forma de programación, pero ¿por qué se recomienda aprender lenguajes de programación funcionales?
oop
functional-programming
Swapnil Kotwal
fuente
fuente
Respuestas:
Definición: Un lenguaje imperativo usa una secuencia de enunciados para determinar cómo alcanzar un objetivo determinado. Se dice que estas declaraciones cambian el estado del programa a medida que cada una se ejecuta a su vez.
Ejemplos: Java es un lenguaje imperativo. Por ejemplo, se puede crear un programa para agregar una serie de números:
Cada declaración cambia el estado del programa, desde la asignación de valores a cada variable hasta la adición final de esos valores. Usando una secuencia de cinco declaraciones, se le dice explícitamente al programa cómo sumar los números 5, 10 y 15.
Lenguajes funcionales: el paradigma de programación funcional se creó explícitamente para admitir un enfoque funcional puro para la resolución de problemas. La programación funcional es una forma de programación declarativa.
Ventajas de las funciones puras: La razón principal para implementar transformaciones funcionales como funciones puras es que las funciones puras son componibles: es decir, autónomas y sin estado. Estas características aportan una serie de beneficios, que incluyen los siguientes: Mayor legibilidad y facilidad de mantenimiento. Esto se debe a que cada función está diseñada para realizar una tarea específica dados sus argumentos. La función no depende de ningún estado externo.
Desarrollo reiterativo más fácil. Debido a que el código es más fácil de refactorizar, los cambios en el diseño a menudo son más fáciles de implementar. Por ejemplo, suponga que escribe una transformación complicada y luego se da cuenta de que parte del código se repite varias veces en la transformación. Si refactoriza a través de un método puro, puede llamar a su método puro a voluntad sin preocuparse por los efectos secundarios.
Pruebas y depuración más fáciles. Debido a que las funciones puras se pueden probar más fácilmente de forma aislada, puede escribir código de prueba que llame a la función pura con valores típicos, casos límite válidos y casos límite no válidos.
Para personas OOP o lenguajes imperativos:
Los lenguajes orientados a objetos son buenos cuando tiene un conjunto fijo de operaciones sobre cosas y a medida que su código evoluciona, principalmente agrega cosas nuevas. Esto se puede lograr agregando nuevas clases que implementen métodos existentes y las clases existentes se dejen solas.
Los lenguajes funcionales son buenos cuando tiene un conjunto fijo de cosas y, a medida que su código evoluciona, agrega principalmente nuevas operaciones en cosas existentes. Esto se puede lograr agregando nuevas funciones que computan con los tipos de datos existentes y las funciones existentes se dejan solas.
Contras:
Depende de los requisitos del usuario para elegir la forma de programación, por lo que hay daño solo cuando los usuarios no eligen la forma correcta.
Cuando la evolución va por el camino equivocado, tienes problemas:
fuente
Aquí está la diferencia:
Imperativo:
... y así sucesivamente ...
Declarativo, de lo que funcional es una subcategoría:
... y así sucesivamente ...
Resumen: En los idiomas imperativos, le dice a la computadora cómo cambiar bits, bytes y palabras en su memoria y en qué orden. En los funcionales, le decimos a la computadora qué cosas, acciones, etc. son. Por ejemplo, decimos que el factorial de 0 es 1, y el factorial de cualquier otro número natural es el producto de ese número y el factorial de su predecesor. No decimos: Para calcular el factorial de n, reserve una región de memoria y almacene 1 allí, luego multiplique el número en esa región de memoria con los números 2 a n y almacene el resultado en el mismo lugar, y al final, la región de memoria contendrá el factorial.
fuente
La mayoría de los lenguajes modernos son en cierto grado imperativos y funcionales, pero para comprender mejor la programación funcional, será mejor tomar un ejemplo de lenguaje funcional puro como Haskell en contraste con el código imperativo en un lenguaje no tan funcional como java / c #. Creo que siempre es fácil de explicar con un ejemplo, así que a continuación hay uno.
Programación funcional: calcular factorial de n es decir n! es decir, nx (n-1) x (n-2) x ... x 2 X 1
Tenga en cuenta que Haskel permite la sobrecarga de funciones al nivel del valor del argumento. A continuación se muestra un ejemplo de código imperativo para aumentar el grado de imperativo:
Esta lectura puede ser una buena referencia para comprender cómo el código imperativo se enfoca más en cómo parte, estado de la máquina (en bucle), orden de ejecución, control de flujo.
El ejemplo posterior puede verse como el código java / c # lang aproximadamente y la primera parte como una limitación del lenguaje en sí mismo en contraste con Haskell para sobrecargar la función por valor (cero) y, por lo tanto, se puede decir que no es un lenguaje funcional purista, por otro lado mano se puede decir que es compatible con el programa funcional. hasta cierto punto.
Divulgación: ninguno de los códigos anteriores se prueba / ejecuta, pero es de esperar que sea lo suficientemente bueno como para transmitir el concepto; También agradecería comentarios para cualquier corrección :)
fuente
return n * factorial(n-1);
?n * (n-1)
La programación funcional es una forma de programación declarativa, que describe la lógica de la computación y el orden de ejecución se desestima por completo.
Problema: quiero cambiar esta criatura de un caballo a una jirafa.
Cada elemento se puede ejecutar en cualquier orden para producir el mismo resultado.
La programación imperativa es de procedimiento. El estado y el orden son importantes.
Problema: quiero estacionar mi auto.
Cada paso debe hacerse para llegar al resultado deseado. Entrar al garaje mientras la puerta del garaje está cerrada daría como resultado una puerta de garaje rota.
fuente
La programación funcional es "programación con funciones", donde una función tiene algunas propiedades matemáticas esperadas, incluida la transparencia referencial. A partir de estas propiedades, fluyen propiedades adicionales, en particular pasos de razonamiento familiares habilitados por la sustituibilidad que conducen a pruebas matemáticas (es decir, justifican la confianza en un resultado).
Se sigue que un programa funcional es simplemente una expresión.
Puede ver fácilmente el contraste entre los dos estilos observando los lugares en un programa imperativo donde una expresión ya no es referencialmente transparente (y, por lo tanto, no se construye con funciones y valores, y no puede ser parte de una función). Los dos lugares más obvios son: mutación (por ejemplo, variables) otros efectos secundarios del flujo de control no local (por ejemplo, excepciones)
En este marco de programas como expresiones que se componen de funciones y valores, se construye un paradigma práctico completo de lenguajes, conceptos, "patrones funcionales", combinadores y varios sistemas de tipos y algoritmos de evaluación.
Según la definición más extrema, casi cualquier lenguaje, incluso C o Java, puede llamarse funcional, pero por lo general las personas reservan el término para lenguajes con abstracciones específicamente relevantes (como cierres, valores inmutables y ayudas sintácticas como la coincidencia de patrones). En lo que respecta al uso de la programación funcional, implica el uso de functinas y el código de compilación sin efectos secundarios. solía escribir pruebas
fuente
El estilo de programación imperativo se practicó en el desarrollo web desde 2005 hasta 2013.
Con la programación imperativa, escribimos el código que enumeraba exactamente lo que nuestra aplicación debería hacer, paso a paso.
El estilo de programación funcional produce abstracción a través de formas inteligentes de combinar funciones.
Se menciona la programación declarativa en las respuestas y respecto a eso diré que la programación declarativa enumera algunas reglas que debemos seguir. Luego proporcionamos lo que llamamos un estado inicial de nuestra aplicación y dejamos que esas reglas definan cómo se comporta la aplicación.
Ahora, estas descripciones rápidas probablemente no tengan mucho sentido, así que veamos las diferencias entre la programación imperativa y declarativa al pasar por una analogía.
Imagine que no estamos construyendo software, sino que horneamos pasteles para vivir. Quizás somos malos panaderos y no sabemos cómo hornear un delicioso pastel como deberíamos.
Entonces nuestro jefe nos da una lista de instrucciones, lo que conocemos como una receta.
La receta nos dirá cómo hacer un pastel. Una receta está escrita en un estilo imperativo como este:
La receta declarativa haría lo siguiente:
1 taza de harina, 1 huevo, 1 taza de azúcar - Estado inicial
Reglas
Por lo tanto, los enfoques imperativos se caracterizan por enfoques paso a paso. Comienzas con el paso uno y vas al paso 2 y así sucesivamente.
Eventualmente terminas con algún producto final. Entonces, al hacer este pastel, tomamos estos ingredientes, los mezclamos, los ponemos en una sartén y en el horno y usted obtiene su producto final.
En un mundo declarativo, es diferente. En la receta declarativa separaríamos nuestra receta en dos partes separadas, comenzando con una parte que enumere el estado inicial de la receta, como las variables. Entonces, nuestras variables aquí son las cantidades de nuestros ingredientes y su tipo.
Tomamos el estado inicial o los ingredientes iniciales y les aplicamos algunas reglas.
Así que tomamos el estado inicial y los pasamos a través de estas reglas una y otra vez hasta que tengamos un pastel de fresa de ruibarbo listo para comer o lo que sea.
Entonces, en un enfoque declarativo, tenemos que saber cómo estructurar adecuadamente estas reglas.
Entonces, las reglas que podríamos querer examinar nuestros ingredientes o nuestro estado, si se mezclan, póngalos en una sartén.
Con nuestro estado inicial, eso no coincide porque aún no hemos mezclado nuestros ingredientes.
Entonces, la regla 2 dice que si no se mezclan, mézclelos en un tazón. De acuerdo, sí, esta regla se aplica.
Ahora tenemos un tazón de ingredientes mezclados como nuestro estado.
Ahora aplicamos ese nuevo estado a nuestras reglas nuevamente.
Entonces, la regla 1 dice que si los ingredientes se mezclan, colóquelos en una sartén, está bien, sí, ahora la regla 1 se aplica, vamos a hacerlo.
Ahora tenemos este nuevo estado donde se mezclan los ingredientes y en una sartén. La regla 1 ya no es relevante, la regla 2 no se aplica.
La regla 3 dice que si los ingredientes están en una sartén, colóquelos en el horno, genial esa regla es lo que se aplica a este nuevo estado, vamos a hacerlo.
Y terminamos con una deliciosa tarta de manzana caliente o lo que sea.
Ahora, si eres como yo, puedes estar pensando, ¿por qué todavía no estamos haciendo una programación imperativa? Esto tiene sentido.
Bueno, para flujos simples, sí, pero la mayoría de las aplicaciones web tienen flujos más complejos que el diseño de programación imperativo no puede capturar adecuadamente.
En un enfoque declarativo, podemos tener algunos ingredientes iniciales o estado inicial como
textInput=“”
, una sola variable.Tal vez el ingreso de texto comienza como una cadena vacía.
Tomamos este estado inicial y lo aplicamos a un conjunto de reglas definidas en su solicitud.
Si un usuario ingresa texto, actualice el ingreso de texto. Bueno, ahora eso no se aplica.
Si se representa la plantilla, calcule el widget.
Bueno, nada de esto aplica, por lo que el programa solo esperará a que suceda un evento.
Entonces, en algún momento, un usuario actualiza la entrada de texto y luego podemos aplicar la regla número 1.
Podemos actualizar eso a
“abcd”
Así que acabamos de actualizar nuestro texto y las actualizaciones de entrada de texto, la regla número 2 no se aplica, la regla número 3 dice si la entrada de texto es actualizada, lo que acaba de ocurrir, luego vuelve a renderizar la plantilla y luego volvemos a la regla 2 que dice si la plantilla se representa , calcular el widget, está bien vamos a calcular el widget.
En general, como programadores, queremos luchar por diseños de programación más declarativos.
Imperativo parece más claro y obvio, pero un enfoque declarativo se adapta muy bien para aplicaciones más grandes.
fuente
• Lenguajes imperativos:
Ejecución eficiente
Semántica compleja
Sintaxis compleja
La concurrencia está diseñada por programadores
Pruebas complejas, no tiene transparencia referencial, tiene efectos secundarios.
• Idiomas funcionales:
Semántica simple
Sintaxis simple
Ejecución menos eficiente
Los programas se pueden hacer automáticamente concurrentes
Pruebas simples, tiene transparencia referencial, no tiene efectos secundarios.
fuente
Creo que es posible expresar la programación funcional de manera imperativa:
if... else
/switch
declaracionesHay grandes problemas con este enfoque:
La programación funcional, el tratamiento de funciones / métodos como objetos y la adopción de la apatridia, nació para resolver esos problemas, creo.
Ejemplo de usos: aplicaciones frontend como Android, iOS o lógicas de aplicaciones web incl. comunicación con el backend.
Otros desafíos al simular la programación funcional con código imperativo / de procedimiento:
También creo que al final del día, los compiladores traducirán el código funcional al código ensamblador o de máquina, que es imprescindible / procesal. Sin embargo, a menos que escriba ensamblado, ya que los humanos escriben código con lenguaje de alto nivel / legible para humanos, la programación funcional es la forma más apropiada de expresión para los escenarios enumerados
fuente
Sé que esta pregunta es más antigua y otras ya la explicaron bien, me gustaría dar un ejemplo de problema que explica lo mismo en términos simples.
Problema: escribir la tabla del 1.
Solución: -
Por estilo imperativo: =>
Por estilo funcional: =>
Explicación en estilo imperativo, escribimos las instrucciones más explícitamente y a las que podemos llamar de una manera más simplificada.
Donde, como en el estilo funcional, las cosas que se explican por sí mismas serán ignoradas.
fuente