Tecnología

Programación funcional: características, ejemplos, ventajas, desventajas


La programación funcional corresponde al patrón de programación que se fundamenta en el concepto de enunciar el proceder de un programa como un modelo funcional matemático más que como secuencias explícitas de instrucciones a un procesador, que es el concepto principal en la programación imperativa.

El lenguaje funcional le da énfasis a las sentencias y términos en lugar de ejecutar instrucciones. En esta programación, el resultado solo dependerá de los parámetros que se pasen a una función, a diferencia de otros tipos que obedecen a un estado local o global.

Su nombre proviene de las funciones matemáticas, que son la asignación de un conjunto de entradas a un conjunto de salidas. Una función matemática realmente no realiza ninguna labor, sino que describe el modelo de un proceso, explicando por medio de una fórmula lo que un conjunto de entradas produce en una función.

Índice del artículo

Ideas básicas

El fundamento en que se basó la programación funcional fue el cálculo lambda, que fue desarrollado durante la tercera década del siglo XX para definir y aplicar funciones. LISP fue el primer lenguaje de programación de este tipo, diseñado en 1960.

Aunque la mayoría de los lenguajes de programación consisten en entradas, salidas y variables externas que se pueden configurar o usar desde las funciones, la programación funcional lo evita. La idea es que cada vez que se llame a una función con los mismos parámetros, deberá devolver el mismo valor.

Características

Los lenguajes de programación funcional se denominan aplicativos, debido a que las funciones se aplican a sus parámetros, además de declarativos y no procesales, ya que las definiciones especifican qué se quiere calcular y no cómo se calcula.

Funciones puras

Una función es pura cuando no tiene efectos secundarios observables, como alteración de las variables externas, cambios en el sistema de archivos, etc.

Estas funciones se consideran convincentes, ya que no cambiarán expresamente ninguna variable de la que pudieran depender otras partes del código en algún momento. Pareciera incómodo codificar con estas restricciones, pero se debe considerar que estas funciones son deterministas, predecibles y componibles.

Funciones de primera clase

Las funciones se consideran como valores que se pueden asignar a variables, por lo cual se las puede pasar hacia y retornar desde otras funciones. Es decir, una función se puede usar como si fuera un parámetro o como un valor que se está retornando.

Esto implica que se pueda transmitir la función como tal, en lugar de únicamente el resultado de la función. Por ejemplo, consideremos la función double(x), la cual retorna el doble del valor de su parámetro de entrada. Así, double(2) retornaría 4.

Como es una función de primera clase, el código (double(double(2)), sería lo mismo que el código double(4). Esto permite anidar una función como parámetro de otra y así sucesivamente.

Transparencia referencial

Se refiere a que en este patrón de programación no existen las sentencias de asignación. Es decir, se deberán definir nuevas variables si se desea almacenar valores adicionales. Por tanto, el estado de una variable es constante en todo momento.

Esto elimina la más mínima posibilidad de efectos indeseados, porque cualquier variable puede ser reemplazada por su valor real durante cualquier punto de ejecución del programa.

Recursividad

En la programación funcional no existen los bucles “for” y “while”. En su lugar, para la iteración se depende de la recursividad. La recursión se implementa utilizando funciones recursivas, que se llaman a sí mismas de forma repetitiva hasta alcanzar el caso base.

Inmutabilidad

Las variables son inmutables, es decir, no es posible modificar una variable una vez que se ha inicializado. Aunque se puede crear una nueva variable, no se permiten modificar las variables existentes.

Ejemplos

Enfoques imperativos y declarativos

Con un ejemplo se puede analizar la diferencia entre estos enfoques, realizando la misma operación en ambas disposiciones, que es filtrar los números impares de una lista mientras se sustituyen por 5 los números pares menores de 5.

Es el mismo cálculo, con el mismo resultado. Sin embargo, como se puede ver, el código imperativo es detallado y no está claro de inmediato. Por otro lado, el enfoque declarativo es legible y explícito, porque se centra en lo que se quiere obtener.

Funciones puras

Se puede aclarar lo que se define como funciones puras e impuras con algunos ejemplos básicos:

Funciones como objetos de primera clase

Significa usar las funciones de la misma manera que se usan los datos. Por tanto, se pueden pasar como parámetros a otra función. En el siguiente ejemplo se puede pasar la función int como parámetro a la función map:

>>> list(map(int, [“1”, “2”, “3”]))

[1, 2, 3]

Se pueden asignar a variables y retornarlas. Por ejemplo, en el siguiente código se puede asignar la función hello_world, ejecutando luego la variable como una función.

Ventajas

– Enfocarse en lo que se quiere lograr (declarativo) y no en cómo lograrlo (imperativo).

– No contienen sentencias de asignación, por lo que después de que se les da un valor a las variables, ya no cambiarán. Por tanto, los programas funcionales no contienen efectos secundarios.

– El flujo lógico es claro, ya que el estado está menos disperso y no se modifica implícitamente.

– Admite el concepto de evaluación diferida, lo que significa que el valor solo se evalúa y almacena cuando sea necesario.

– Como las funciones puras no cambian ningún estado y dependen completamente de la entrada, son fáciles de entender. El valor de retorno dado por tales funciones es el mismo que el resultado producido por ellas.

– Debido a la naturaleza de las funciones puras de evitar que cambien las variables o cualquier dato externo, se hace eficaz la implementación de la concurrencia.

– Las funciones se tratan como valores, pasándose a otras funciones como parámetros. Esto mejora la comprensión y legibilidad del código.

– Las funciones puras toman los parámetros una vez, produciendo una salida inmutable. Al utilizar valores inalterables, se facilita la depuración y las pruebas.

Más cortos y fáciles de entender

Son más cortos y fáciles de entender que los imperativos. Estudios han demostrado que la productividad promedio del programador en términos de líneas de código es más o menos la misma para cualquier lenguaje de programación, traduciéndose en una mayor productividad.

Sin flujo de control

Al llamar a una función no se puede tener un efecto diferente al del cálculo de su resultado. Esto descarta una fuente importante de errores, haciendo también que el orden de ejecución sea irrelevante, ya que ningún efecto secundario podrá cambiar el valor de una expresión, pudiendo evaluarse en cualquier momento.

Al programador se le apacigua la carga de establecer un flujo de control. Como las expresiones se pueden evaluar en cualquier momento, las variables se podrán reemplazar por sus valores.

Esta autonomía favorece que los programas funcionales sean más manejables matemáticamente que los programas convencionales.

Desventajas

– El paradigma de la programación funcional no es sencillo, por lo que se hace difícil de entender para un principiante.

– Es difícil de mantener, ya que durante la codificación evolucionan muchos objetos.

– En algunos casos, al escribir funciones puras se provoca una reducción en la legibilidad del código.

– Los valores inmutables en combinación con la recursividad pueden conllevar a una drástica reducción en el rendimiento del sistema.

– La reutilización es muy complicada y necesita una constante refactorización.

– Escribir programas con un estilo recursivo en lugar de usar lazos o bucles pudiera ser una tarea muy desalentadora.

– Los objetos puede que no representen el problema correctamente.

– Aunque escribir funciones puras resulta ser sencillo, combinarlas con el resto de la aplicación y con las operaciones de entrada/salida es bastante difícil

Aplicaciones

La programación de inteligencia artificial se realiza en lenguajes de programación funcional y las técnicas de inteligencia artificial migran a aplicaciones del mundo real.

Sobresale también en la implementación de modelos matemáticos complejos. Por esta razón, uno de los principales usos de los lenguajes funcionales ha sido tradicionalmente académico. Es útil para desarrollar especificaciones ejecutables e implementaciones de prototipos.

Muchos lenguajes funcionales también se destacan para implementar el procesamiento paralelo. Esto se debe a su capacidad de aprovechar las funciones puras, que siempre retornan el mismo valor independientemente del orden en que se ejecutan.

Metodología funcional

WhatsApp utiliza el lenguaje de programación Erlang, que sigue el modelo de programación funcional, permitiendo así que más de una centena de sus empleados manejen los datos pertenecientes a unas 1.600 millones de personas.

Otro portador importante del estilo de programación funcional es Haskell. Es utilizado por Facebook en su sistema antispam. Incluso JavaScript, uno de los lenguajes de programación más utilizados, hace alarde de las propiedades de un lenguaje funcional de tipo dinámico.

Lenguajes que soportan programación funcional

D

Fue diseñado después de C++, obteniendo todos sus beneficios a la vez que elimina sus debilidades observadas por tener que ser compatible con C.

Erlang

Es altamente escalable y concurrente, haciéndolo ideal para las telecomunicaciones y otras aplicaciones que reciben cantidades masivas de datos en un orden impredecible.

Haskell

Este es un lenguaje puro de programación funcional, que utiliza para ello el cálculo Lambda.

ML

Se utiliza en aplicaciones matemáticas, científicas, financieras, analíticas y de otros tipos. Una de sus fortalezas es hacer software para manejar otros programas.

Objective Caml

Es un lenguaje de código abierto que se basa en Caml. Tiende a crear programas muy livianos, ayudando a que estos se puedan cargar y ejecutar más rápidamente que los creados por otros lenguajes.

Scheme

Está basado en la sintaxis de LISP y la estructura de ALGOL. Gracias a su simplicidad, se utiliza en muchos cursos de informática como introducción al diseño de programas para mostrar algunos de los fundamentos de la programación informática.

Referencias

  1. Who Is Hosting This (2019). Learn Functional Programming: This Style of Coding Will Blow Your Mind. Tomado de: whoishostingthis.com.
  2. Andrea Bertoli (2019). An Adequate Introduction to Functional Programming. Tomado de: dev.to.
  3. Hacker Earth (2020). Functional Programming. Tomado de: hackerearth.com.
  4. Clojure (2020). Functional Programming. Tomado de: clojure.org.
  5. Akhil Bhadwal (2020). Functional Programming: Concepts, Advantages, Disadvantages, and Applications. Hackr. Tomado de: hackr.io.
  6. Guru99 (2020). What is Functional Programming? Tutorial with Example. Tomado de: guru99.com.