¿Por qué los desarrolladores se enamoran de la programación funcional?

La programación funcional (FP) ha existido durante 60 años , pero hasta ahora siempre ha tenido un ámbito de uso bastante limitado. Si bien las empresas que cambian el mundo como Google se basan en conceptos básicos , el programador moderno promedio sabe muy poco, si es que algo, sobre este fenómeno.



Pero eso cambiará pronto. Cada vez se integran más conceptos de FP en lenguajes como Java y Python . Y los lenguajes más modernos como Haskell son completamente funcionales. Para poner la programación funcional en términos simples







, entonces esta es la creación de funciones para trabajar con variables inmutables. En contraste, la programación orientada a objetos es cuando se usa un conjunto relativamente constante de funciones, y el programador está principalmente ocupado modificando variables existentes y creando nuevas.



FP, por su naturaleza, es adecuado para resolver problemas urgentes, como el análisis de datos y el aprendizaje automático . Esto no significa que deba despedirse de la programación orientada a objetos y cambiar completamente a la programación funcional. Es simplemente útil para el programador moderno conocer los principios básicos de FP, que le permitirán aplicar estos principios donde puedan serle útiles.



La programación funcional se trata de eliminar los efectos secundarios



Para comprender los principios de la programación funcional, primero debe comprender qué es una "función". Puede parecer aburrido, pero al final, te permitirá ver lo que a primera vista es imperceptible. Así que hablemos de funciones.



Una función, en términos simples, es una entidad que convierte alguna entrada que se le pasa en datos de salida que devuelve al lugar de llamada. Es cierto, de hecho, no siempre todo parece tan simple. Eche un vistazo a la siguiente función de Python:



def square(x):
    return x*x


Esta función es extremadamente sencilla. Toma un argumento, xque probablemente sea de tipo int, y quizás de tipo floato double, y devuelve el resultado de xcuadrarlo.



Y aquí hay otra función:



global_list = []
def append_to_list(x):
    global_list.append(x)


A primera vista, parece que acepta xalgún tipo y no devuelve nada, ya que no hay expresión en él return. ¡Pero no saquemos conclusiones precipitadas!



La función no puede funcionar normalmente si la variable no se declara de antemano global_list. El resultado de esta función es una lista modificada almacenada en global_list. Aunque no se global_listdeclara como un valor que se pasa a la entrada de una función, esta variable cambia después de que se llama a la función.



append_to_list(1)
append_to_list(2)
global_list


Después de un par de llamadas a la función del ejemplo anterior global_list, la lista ya no será una lista vacía, sino una lista [1,2]. Esto nos permite decir que la lista, de hecho, es el valor proporcionado a la entrada de la función, aunque esto no se fija de ninguna manera cuando se declara la función. Esto puede ser un problema.



Deshonestidad al declarar funciones



Estos valores implícitos de entrada o salida tienen un nombre oficial: efectos secundarios. Estamos usando ejemplos muy simples aquí, pero en programas más complejos, los efectos secundarios pueden conducir a complicaciones reales .



Piense en cómo probaría la función append_to_list. No será suficiente leer la primera línea de su declaración y descubrir que debe probarse pasándole algún valor x. En su lugar, deberá leer todo el código de la función, averiguar qué está sucediendo exactamente allí, declarar una variable global_listy luego probar la función. Lo que en nuestro ejemplo simple no parece causar ninguna dificultad particular, en programas que constan de miles de líneas de código se verá completamente diferente.



Afortunadamente, el problema anterior es fácil de solucionar. Solo necesita ser honesto al especificar qué debe ir exactamente a la entrada de la función. La siguiente versión de nuestra función se ve mucho mejor que la anterior:



newlist = []
def append_to_list2(x, some_list):
    some_list.append(x)
append_to_list2(1,newlist)
append_to_list2(2,newlist)
newlist


No hemos cambiado mucho en este código. Como resultado, la función en newlist, como antes global_list, resulta [1,2], y todo lo demás se ve igual que antes.



Sin embargo, hicimos un cambio significativo en este código. Nos deshicimos de los efectos secundarios. Y esto es muy bueno.



Es decir, ahora, después de leer la primera línea de la declaración de la función, sabemos exactamente con qué datos de entrada trabaja. Como resultado, si el programa no se comporta como se esperaba, es fácil probar todas las funciones que contiene y encontrar la que no funciona correctamente. Las funciones puras son más fáciles de mantener.



La programación funcional es escribir funciones puras



Una función que, cuando se declara, indica claramente lo que toma y lo que devuelve es una función sin efectos secundarios. Una función sin efectos secundarios es una función pura.



Aquí hay una definición muy simple de programación funcional. Se trata de programas de escritura que constan únicamente de funciones puras. Las funciones puras nunca modifican los datos que se les pasan, solo crean nuevos y los devuelven. (Tenga en cuenta que hice un poco de trampa en el ejemplo anterior. Está escrito en el espíritu de la programación funcional, pero en él la función modifica la lista de variables globales. Pero aquí solo estamos examinando los principios básicos de FP, por lo que hice exactamente eso. Si lo desea, aquí puede encontrar ejemplos más estrictos de funciones puras.)



Además, al trabajar con funciones puras, puede esperar que, al recibir los mismos datos como entrada, siempre generen la misma salida. Y las funciones que no son puras pueden depender de algún tipo de variables globales. Como resultado, ellos, al recibir la misma entrada, pueden producir resultados diferentes, dependiendo del valor de las variables globales. Este hecho puede complicar significativamente la depuración y el mantenimiento del código.



Existe una regla básica para detectar efectos secundarios. Dado que al declarar funciones puras se debe definir claramente qué reciben como entrada y retorno, las funciones que no aceptan ni devuelven nada no quedarán limpias. Si decide incorporar técnicas de programación funcional en su proyecto, lo primero que probablemente querrá hacer es verificar las declaraciones de sus funciones.



Qué programación funcional no es



▍Mapear y reducir funciones



Los bucles son mecanismos que nada tienen que ver con la programación funcional. Eche un vistazo a los siguientes bucles de Python:



integers = [1,2,3,4,5,6]
odd_ints = []
squared_odds = []
total = 0
for i in integers:
    if i%2 ==1
        odd_ints.append(i)
for i in odd_ints:
    squared_odds.append(i*i)
for i in squared_odds:
    total += i


Con la ayuda de este código, resolvemos problemas simples, pero resultó ser bastante largo. Y, además, no es funcional, ya que aquí se modifican las variables globales.



Y ahora, otra versión de este código:



from functools import reduce
integers = [1,2,3,4,5,6]
odd_ints = filter(lambda n: n % 2 == 1, integers)
squared_odds = map(lambda n: n * n, odd_ints)
total = reduce(lambda acc, n: acc + n, squared_odds)


Este es un código completamente funcional. Es mas corto. Es más rápido porque no tiene que iterar sobre muchos elementos de la matriz. Y, si usted entiende las funciones filter, mapy reduce, resulta que este código no es mucho más difícil de entender que aquel en el que se utilizan bucles.



Esto no quiere decir que, en cualquier código de función se utiliza map, reducey otras funciones. Y esto no significa que para manejar tales funciones, necesite conocer la programación funcional. El punto es que estas funciones se utilizan a menudo para deshacerse de bucles.



▍ Funciones Lambda



Cuando las personas hablan sobre la historia de la programación funcional, a menudo comienzan hablando de la invención de las funciones lambda. Pero aunque las funciones lambda son sin duda la piedra angular de la programación funcional, no son la causa principal de FP.



Las funciones Lambda son herramientas que se pueden utilizar para escribir programas con un estilo funcional. Pero estas funciones también se pueden utilizar en programación orientada a objetos.



▍Escritura estática



El ejemplo anterior no está escrito de forma estática. Sin embargo, es una muestra de código funcional.



Aunque la escritura estática agrega una capa adicional de seguridad a su código, no es un requisito para crear código funcional. Sin embargo, puede ser una buena adición al estilo funcional de programación.



Cabe señalar que algunos lenguajes son más fáciles de programar en un estilo funcional que otros.



Algunos idiomas son "más funcionales" que otros



▍Perl



Perl tiene un enfoque para lidiar con los efectos secundarios que lo distingue de la mayoría de los otros idiomas. Es decir, tiene una "variable mágica" $_que trae efectos secundarios al nivel de una de las características principales del lenguaje. Perl tiene sus méritos, pero no trataría de hacer programación funcional en este lenguaje.



▍Java



Le deseo la mejor de las suertes escribiendo código Java funcional. No te hará daño. Primero, la palabra clave ocupará la mitad del código static. En segundo lugar, la mayoría de los programadores de Java llamarán a su código un malentendido.



Esto no significa que Java sea un lenguaje inadecuado. Pero no está diseñado para resolver el tipo de problemas para los que la programación funcional es ideal. Por ejemplo, para la gestión de bases de datos o para el desarrollo de aplicaciones del campo del aprendizaje automático.



▍Scala



Scala es un idioma interesante. Su objetivo es unificar la programación funcional y orientada a objetos. Si esto le parece extraño, sepa que no está solo. Después de todo, la programación funcional tiene como objetivo eliminar por completo los efectos secundarios. La programación orientada a objetos se trata de limitar los efectos secundarios a los objetos.



Con esto en mente, podemos decir que muchos desarrolladores ven Scala como un lenguaje que les ayudará a pasar de la programación orientada a objetos a la programación funcional. El uso de Scala puede facilitarles la transición a un estilo de programación completamente funcional en el futuro.



▍Python



El estilo de programación funcional se recomienda en Python. Esto se puede entender si tenemos en cuenta que cada función, por defecto, tiene al menos un parámetro - self. Esto está, en muchos sentidos, en el espíritu de " Zen Python ": "Explícito es mejor que implícito".



▍Clojure



Clojure, según el creador del lenguaje, es aproximadamente un 80% funcional. Todos los valores son inmutables por defecto. Pero esto es exactamente lo que se necesita para escribir código funcional. Sin embargo, puede evitar esto mediante el uso de contenedores mutables, en los que se colocan valores inmutables. Y si extrae el valor del contenedor, vuelve a ser inmutable.



▍Haskell



Es uno de los pocos lenguajes completamente funcionales y de tipo estático. Si bien su uso en el proceso de desarrollo puede parecer que lleva demasiado tiempo implementar mecanismos funcionales, tal esfuerzo dará sus frutos muchas veces durante la depuración del código. Este idioma no es tan fácil de aprender como otros, pero aprenderlo definitivamente es una inversión que vale la pena.



Salir



Cabe señalar que ahora sigue siendo el comienzo de la era del big data. El big data está llegando, y no solo, sino con un amigo, con programación funcional.



La programación funcional, en comparación con la programación orientada a objetos, sigue siendo un fenómeno de nicho. Es cierto que si consideramos la integración de los principios de FP en Python y otros lenguajes como un fenómeno significativo, podemos concluir que la programación funcional está ganando popularidad.



Y esto tiene sentido, ya que la programación funcional se muestra bien trabajando con bases de datos, en programación paralela, en el campo del aprendizaje automático. Y en la última década, todo esto ha ido en aumento.



Si bien el código orientado a objetos tiene innumerables beneficios, no debe descartar los beneficios del código funcional. Si un programador aprende algunos de los principios básicos de FP, entonces, en la mayoría de los casos, esto puede ser suficiente para mejorar su nivel profesional. Este conocimiento también le ayudará a prepararse para un "futuro funcional".



¿Qué opinas de la programación funcional?






All Articles