Realmente estoy teniendo dificultades para entender la diferencia entre los paradigmas de programación funcional y de procedimiento .
Aquí están los dos primeros párrafos de la entrada de Wikipedia sobre programación funcional :
En informática, la programación funcional es un paradigma de programación que trata la computación como la evaluación de funciones matemáticas y evita estados y datos mutables. Enfatiza la aplicación de funciones, en contraste con el estilo de programación imperativa, que enfatiza los cambios de estado. La programación funcional tiene sus raíces en el cálculo lambda, un sistema formal desarrollado en la década de 1930 para investigar la definición de funciones, la aplicación de funciones y la recursividad. Muchos lenguajes de programación funcionales pueden verse como elaboraciones del cálculo lambda.
En la práctica, la diferencia entre una función matemática y la noción de "función" utilizada en la programación imperativa es que las funciones imperativas pueden tener efectos secundarios, cambiando el valor del estado del programa. Debido a esto, carecen de transparencia referencial, es decir, una misma expresión de lenguaje puede dar como resultado valores diferentes en momentos diferentes según el estado del programa en ejecución. Por el contrario, en el código funcional, el valor de salida de una función depende solo de los argumentos que se ingresan a la función, por lo que llamar a una función
f
dos veces con el mismo valor para un argumentox
producirá el mismo resultadof(x)
ambas veces. La eliminación de efectos secundarios puede facilitar la comprensión y la predicción del comportamiento de un programa, que es una de las motivaciones clave para el desarrollo de la programación funcional.
En el párrafo 2 donde dice
Por el contrario, en el código funcional, el valor de salida de una función depende solo de los argumentos que se ingresan a la función, por lo que llamar a una función
f
dos veces con el mismo valor para un argumentox
producirá el mismo resultado enf(x)
ambas ocasiones.
¿No es ese el mismo caso exacto para la programación procedimental?
¿Qué se debe buscar en procedimientos frente a funcionales que se destacan?
Respuestas:
Programación funcional
La programación funcional se refiere a la capacidad de tratar las funciones como valores.
Consideremos una analogía con los valores "regulares". Podemos tomar dos valores enteros y combinarlos usando el
+
operador para obtener un nuevo entero. O podemos multiplicar un número entero por un número de punto flotante para obtener un número de punto flotante.En la programación funcional, podemos combinar dos valores de función para producir un nuevo valor de función utilizando operadores como componer o lift . O podemos combinar un valor de función y un valor de datos para producir un nuevo valor de datos utilizando operadores como map o fold .
Tenga en cuenta que muchos lenguajes tienen capacidades de programación funcional, incluso lenguajes que normalmente no se consideran lenguajes funcionales. Incluso el abuelo FORTRAN admitía valores de función, aunque no ofrecía muchos operadores de combinación de funciones. Para que un lenguaje se llame "funcional", necesita abarcar las capacidades de programación funcional a lo grande.
Programación procedimental
La programación por procedimientos se refiere a la capacidad de encapsular una secuencia común de instrucciones en un procedimiento de modo que esas instrucciones puedan invocarse desde muchos lugares sin tener que recurrir a copiar y pegar. Como los procedimientos fueron un desarrollo muy temprano en la programación, la capacidad está casi invariablemente vinculada con el estilo de programación exigido por la programación en lenguaje ensamblador o máquina: un estilo que enfatiza la noción de ubicaciones de almacenamiento e instrucciones que mueven datos entre esas ubicaciones.
Contraste
Los dos estilos no son realmente opuestos, solo son diferentes entre sí. Hay lenguajes que abarcan completamente ambos estilos (LISP, por ejemplo). El siguiente escenario puede dar una idea de algunas diferencias en los dos estilos. Escribamos un código para un requisito sin sentido en el que queremos determinar si todas las palabras de una lista tienen un número impar de caracteres. Primero, estilo procedimental:
Daré por sentado que este ejemplo es comprensible. Ahora, estilo funcional:
Trabajando desde adentro hacia afuera, esta definición hace lo siguiente:
compose(odd, length)
combina las funcionesodd
ylength
para producir una nueva función que determina si la longitud de una cadena es impar.map(..., words)
llama a esa nueva función para cada elemento enwords
, finalmente devuelve una nueva lista de valores booleanos, cada uno indicando si la palabra correspondiente tiene un número impar de caracteres.apply(and, ...)
aplica el operador "y" a la lista resultante, y combina todos los valores booleanos para obtener el resultado final.Puede ver en estos ejemplos que la programación de procedimientos se preocupa mucho por mover valores en variables y describir explícitamente las operaciones necesarias para producir el resultado final. En contraste, el estilo funcional enfatiza la combinación de funciones necesarias para transformar la entrada inicial en la salida final.
El ejemplo también muestra los tamaños relativos típicos de código de procedimiento versus funcional. Además, demuestra que las características de rendimiento del código de procedimiento pueden ser más fáciles de ver que las del código funcional. Considere: ¿las funciones calculan las longitudes de todas las palabras de la lista o cada una se detiene inmediatamente después de encontrar la primera palabra de longitud uniforme? Por otro lado, el código funcional permite una implementación de alta calidad para realizar una optimización bastante seria, ya que principalmente expresa la intención en lugar de un algoritmo explícito.
Otras lecturas
Esta pregunta surge mucho ... ver, por ejemplo:
La conferencia del premio Turing de John Backus explica con gran detalle las motivaciones de la programación funcional:
¿Puede la programación liberarse del estilo von Neumann?
Realmente no debería mencionar ese artículo en el contexto actual porque se vuelve bastante técnico, bastante rápido. Simplemente no pude resistirme porque creo que es realmente fundamental.
Anexo - 2013
Los comentaristas señalan que los lenguajes contemporáneos populares ofrecen otros estilos de programación además de procedimental y funcional. Estos lenguajes suelen ofrecer uno o más de los siguientes estilos de programación:
Consulte los comentarios a continuación para ver ejemplos de cómo los ejemplos de pseudocódigo de esta respuesta pueden beneficiarse de algunas de las funciones disponibles en esos otros estilos. En particular, el ejemplo de procedimiento se beneficiará de la aplicación de prácticamente cualquier construcción de nivel superior.
Los ejemplos exhibidos evitan deliberadamente mezclar estos otros estilos de programación para enfatizar la distinción entre los dos estilos en discusión.
fuente
odd_words(words)
definición hace algo diferente a la respuestaallOdd
. Para el filtrado y el mapeo, a menudo se prefieren las listas por comprensión, pero aquíallOdd
se supone que la función reduce una lista de palabras a un solo valor booleano.La diferencia real entre la programación funcional e imperativa es la forma de pensar: los programadores imperativos piensan en variables y bloques de memoria, mientras que los programadores funcionales piensan: "¿Cómo puedo transformar mis datos de entrada en datos de salida?", Su "programa" es la tubería. y conjunto de transformaciones en los datos para llevarlos de la Entrada a la Salida. Esa es la parte interesante en mi opinión, no el bit "No usarás variables".
Como consecuencia de esta mentalidad, los programas de planificación familiar suelen describir lo que sucederá, en lugar del mecanismo específico de cómo sucederá; esto es poderoso porque si podemos establecer claramente lo que significa "Seleccionar", "Dónde" y "Agregar", son libres de intercambiar sus implementaciones, al igual que hacemos con AsParallel () y, de repente, nuestra aplicación de un solo subproceso se escala a n núcleos.
fuente
No, porque el código de procedimiento puede tener efectos secundarios. Por ejemplo, puede almacenar el estado entre llamadas.
Dicho esto, es posible escribir código que satisfaga esta restricción en lenguajes considerados de procedimiento. Y también es posible escribir código que rompa esta restricción en algunos lenguajes considerados funcionales.
fuente
No estoy de acuerdo con la respuesta de WReach. Deconstruyamos un poco su respuesta para ver de dónde viene el desacuerdo.
Primero, su código:
y
Lo primero que hay que tener en cuenta es que está fusionando:
programación, y falta la capacidad de la programación de estilo iterativo para tener un flujo de control más explícito que un estilo funcional típico.
Hablemos rápidamente de estos.
El estilo centrado en la expresión es aquel en el que las cosas, en la medida de lo posible, se evalúan . Aunque los lenguajes funcionales son famosos por su amor por las expresiones, en realidad es posible tener un lenguaje funcional sin expresiones componibles. Voy a inventarme uno, donde no hay expresiones, solo declaraciones.
Esto es más o menos lo mismo que se dio antes, excepto que las funciones están encadenadas puramente a través de cadenas de declaraciones y enlaces.
Un estilo de programación centrado en el iterador podría ser uno de Python. Usemos un estilo puramente iterativo y centrado en el iterador:
Esto no es funcional, porque cada cláusula es un proceso iterativo y están unidas por una pausa explícita y la reanudación de los marcos de pila. La sintaxis puede estar inspirada parcialmente en un lenguaje funcional, pero se aplica a una encarnación completamente iterativa del mismo.
Por supuesto, puedes comprimir esto:
Imperative no se ve tan mal ahora, ¿eh? :)
El punto final fue sobre un flujo de control más explícito. Reescribamos el código original para hacer uso de esto:
Usando iteradores puede tener:
Entonces, ¿de qué sirve un lenguaje funcional si la diferencia está entre:
La principal característica definitiva de un lenguaje de programación funcional es que elimina la mutación como parte del modelo de programación típico. La gente suele pensar que esto significa que un lenguaje de programación funcional no tiene declaraciones o utiliza expresiones, pero estas son simplificaciones. Un lenguaje funcional reemplaza el cálculo explícito con una declaración de comportamiento, sobre la cual el lenguaje luego realiza una reducción.
Restringirse a este subconjunto de funcionalidades le permite tener más garantías sobre el comportamiento de sus programas y esto le permite componerlos con mayor libertad.
Cuando tiene un lenguaje funcional, crear nuevas funciones generalmente es tan simple como componer funciones estrechamente relacionadas.
Esto no es simple, o quizás no sea posible, si no ha controlado explícitamente las dependencias globales de una función. La mejor característica de la programación funcional es que puede crear consistentemente abstracciones más genéricas y confiar en que pueden combinarse en un todo mayor.
fuente
apply
no es la misma operación que unfold
oreduce
, aunque estoy de acuerdo con la buena capacidad de tener algoritmos muy genéricos.apply
significarfold
oreduce
, pero me parece que tiene que estar en este contexto para que devuelva un booleano.En el paradigma procedimental (¿debería decir "programación estructurada" en su lugar?), Ha compartido memoria e instrucciones mutables que la leen / escriben en alguna secuencia (una tras otra).
En el paradigma funcional, tienes variables y funciones (en el sentido matemático: las variables no varían con el tiempo, las funciones solo pueden calcular algo en función de sus entradas).
(Esto está muy simplificado, por ejemplo, los FPL generalmente tienen facilidades para trabajar con memoria mutable, mientras que los lenguajes de procedimiento a menudo pueden admitir procedimientos de orden superior, por lo que las cosas no son tan claras; pero esto debería darle una idea)
fuente
The Charming Python: La programación funcional en Python de IBM Developerworks realmente me ayudó a comprender la diferencia.
Especialmente para alguien que conoce un poco Python, los ejemplos de código de este artículo en los que se contrastan diferentes funciones de manera funcional y procedimental, pueden aclarar la diferencia entre programación procedimental y funcional.
fuente
En la programación funcional, para razonar sobre el significado de un símbolo (variable o nombre de función), solo necesita saber 2 cosas: el alcance actual y el nombre del símbolo. Si tiene un lenguaje puramente funcional con inmutabilidad, ambos son conceptos "estáticos" (perdón por el nombre sobrecargado), lo que significa que puede ver ambos, el alcance actual y el nombre, con solo mirar el código fuente.
En la programación de procedimientos, si desea responder a la pregunta cuál es el valor detrás
x
, también debe saber cómo llegó allí, el alcance y el nombre por sí solos no son suficientes. Y esto es lo que yo vería como el mayor desafío porque esta ruta de ejecución es una propiedad de "tiempo de ejecución" y puede depender de tantas cosas diferentes, que la mayoría de la gente aprende a depurarla y no a intentar recuperar la ruta de ejecución.fuente
Recientemente he estado pensando en la diferencia en términos del problema de expresión . La descripción de Phil Wadler se cita con frecuencia, pero la respuesta aceptada a esta pregunta probablemente sea más fácil de seguir. Básicamente, parece que los lenguajes imperativos tienden a elegir un enfoque del problema, mientras que los lenguajes funcionales tienden a elegir el otro.
fuente
Una diferencia clara entre los dos paradigmas de programación es el estado.
En la programación funcional, se evita el estado. En pocas palabras, no habrá ninguna variable a la que se le asigne un valor.
Ejemplo:
Sin embargo, la programación por procedimientos usa state.
Ejemplo:
fuente