Programación funcional es un paradigma de programación del tipo declarativo, un paradigma es un modelo o mapa de como vemos el mundo real, es una manera o estilo de hacer las cosas, entonces un paradigma de programación es una manera o estilo de como crear software.

Ejemplos de otros paradigmas de programación son:

  • Programación Estructurada
  • Programación orientada a objetos
  • Programación Declarativa
  • Programación Imperativa
  • Programación reactiva

Antes de empezar a explicar la programación funcional, debemos entender que aunque existan muchos paradigmas de programación no quiere decir que debas elegir uno y casarte con él, y luego nunca usar otro en tus desarrollos, ¡no, no, no!, realmente todos los paradigmas son incorrectos desde una perspectiva constructiva, somos seres humanos y los paradigmas son creados por seres humanos imperfectos, lo cual nos lleva a la idea de que hay paradigmas que te permiten resolver un determinado problema de una mejor manera en comparación con otro.

Entonces el enfoque efectivo es utilizar más de un paradigma, es decir, un desarrollo de software eficiente utiliza más de un paradigma según el problema a resolver, así es, determinados paradigmas encajan mejor para determinadas soluciones dentro del desarrollo de software.

Hemos mencionado dos paradigmas de programación, Imperativo y declarativo, pero para los que no saben la diferencia, en la programación imperativa le ordenamos a la computadora paso por paso como obtener cierto resultado, por ejemplo:

const num1 = 1;
const num2 = 2;
const suma = num1 + num2; // 3

En la programación declarativa solo le indicamos que resultado queremos obtener.

Ejemplo en EcmaScript:

// suponiendo que la función suma existe
// No me interesa como realizas la suma, sumar(1, 2) me regresará el valor 3
const suma = sumar(1, 2);

Ejemplo en HTML:

<html>
  <head>
    <title>Quiero un título, no me importa como lo hagas ni en que navegador web lo 
       tengas que mostrar</title>
    </head>
  <body>
    <p>Quiero un párrafo, no me importa como lo hagas ni en que navegador web lo 
      tengas que crear</p>
  </body>
</html>

HTML es declarativo, no nos importa como muestra nuestro título o párrafo, si tiene que hacer operaciones matemáticas y trabajar con pixeles para pintar nuestro párrafo, ni lo que tenga que hacer dependiendo si lo debe mostrar en firefox, IE, Edge, Safari o Chrome.

SELECT nombre, numero_celular FROM chicas_atractivas WHERE edad > 18

En esta consulta SQL, suponiendo que la tabla chicas_atractivas contiene la información de todas las chicas atractivas de México, pero solo nos interesan las que son mayor de edad. Le estamos indicando que es lo que queremos, pero No como obtenerlo, por ejemplo no nos importa como hacer la comparación de la edad, si tiene que hacer la consulta en paralelo con otra, ni nos interesa en que dispositivo físico esta guardada esta información.

Sin efectos colaterales

Ahora bien, todo lo que necesitas saber sobre programación funcional es que ‘No tiene efectos colaterales’. La ausencia de efectos es la esencia de la programación funcional, esto significa que una función no se mete en lo absoluto con datos que existen fuera de ella, si puede utilizar los datos pasados como parámetros, pero no puede modificarlos, todos los datos deben ser inmutables. A este comportamiento se le llama funciones puras.

Sin efectos colaterales nos permite entender todas las demás características de la programación funcional, por mencionar algunas principales:

  • Funciones puras
  • Inmutabilidad
  • Funciones de alto nivel
  • Funciones currificadas
  • Recursividad
  • Menos errores de programación porque no realiza efectos colaterales.

Toda función teniendo ciertos datos de entrada o parámetros, obtendremos un resultado basado en esos parámetros, esto nos da la habilidad de predecir el resultado, tendremos más seguridad de lo que obtendremos por lo que nuestra programación se vuelve más entendible. También vamos a estar seguros de que siempre obtendremos el mismo resultado cada vez que insertemos los mismos datos, ya que una función no depende de más datos externos de la aplicación que puedan cambiar en el tiempo.

Javascript es un lenguaje de programación muy potente y multiparadigma, soporta el paradigma funcional y lo utilizaremos para nuestros ejemplos. La programación funcional tiene sus orígenes en el cálculo lambda

Funciones puras e inmutabilidad

Bueno, realmente ya explicamos de manera indirecta que es una función pura en los párrafos anteriores, pero veamos una definición formal. Una función pura es la que cumple con estas dos características:

  1. Siempre obtendremos el mismo resultado dado los mismos parámetros de entrada.
  2. No tiene ningún efecto colateral observable, no modifica el estado de los datos externos, por lo que todos los datos deben ser inmutables.

Veamos un ejemplo de como cambiar el nombre de una objeto persona usando primero una función imperativa:

function cambiarNombre(nombre) {
  persona.nombre = nombre;
}

const jaime = { nombre: 'Jaime', edad: 30 };

cambiarNombre('Juan');

console.log(jaime); // { nombre: 'Juan', edad: 30 }

En la función imperativa vemos que la función cambia el objeto jaime, el cual seria parte del estado de nuestra aplicación, puede haber otras funciones que cambien al objeto jaime y no sabemos con certeza el estado del objeto jaime en un determinado punto de la ejecución de nuestro programa, esto puede generar problemas si alguien más espera que la propiedad nombre del objeto jaime sea 'jaime'.

Ahora veamos la versión funcional de la función:

function cambiarNombre(nombre, persona) {
  return {
    nombre: nuevoNombre,
    edad: persona.edad
  }
}

const jaime = { nombre: 'Jaime', edad: 30 };
const juan = cambiarNombre(jaime, 'Juan');

console.log(jaime); // { nombre: 'Jaime', edad: 30 }
console.log(juan); // { nombre: 'Juan', edad: 30 }

En la versión funcional cambiarNombre no modifica el objeto jaime, más bien crea un nuevo objeto con la misma edad que jaime y con la propiedad nombre igual a 'Juan', con esto evitamos efectos colaterales por si el objeto jaime es utilizado por otra función u otro programador.

Con la función pura, nos damos cuenta que los datos se manejan sin ser cambiados, es decir, inmutables, los parámetros persona y nombre no son modificados, el objeto jaime nunca es modificado.

Funciones de alto nivel y currificadas

Una función de alto nivel es una función que implementa al menos una de las opciones siguientes:

  • Recibir como parámetro una o más funciones
  • Regresar como resultado una función

Un ejemplo muy común usado en nuestro navegador web es agregar escuchadores de eventos:

<button id="boton">Soy un botón</button>

const boton = document.querySelector('#boton');
boton.addEventListener('click, function () {
  alert('Click sobre el boton');
});

Como vemos pasamos como segundo parámetro del método addEventListener una función anónima (sin nombre) que mostrará un alerta al dar click sobre un botón con id igual a ‘botón’.

Ahora vamos a transformar un arreglo de números en otro arreglo con los valores aumentados al doble.

See the Pen Funciones de alto nivel by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

La función map retorna un nuevo arreglo, no cambia el arreglo original.

Las funciones currificadas son funciones de alto nivel que como resultado regresan otra función, de tal manera que el acto de currificar es convertir una función de más de un parámetro en dos o más funciones que reciben parcialmente esos parámetros en dos o más invocaciones currificadas.

See the Pen Funciones de alto nivel y funciones currificadas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Las funciones flecha o arrow functions nos permiten acceder al contexto de los parámetros de sus definiciones, de esta manera cuando se les define un valor, una arrow function puede ver ese valor. Para lograr lo mismo sin funciones flecha se debe utilizar la variable arguments que existe localmente como variable de todas las funciones en JavaScript.

Función recursiva

Una función recursiva permite dividir un problema grande en pedazos más pequeños, siempre y cuando el problema tenga un patrón que se repite muchas veces, una función recursiva se llama o invoca así misma hasta llegar a un caso base y desde ahí regresar los valores y encontrar la solución.

Una función recursiva está compuesta de dos casos:

  1. El caso base, el cual permite detener la ejecución de subsecuentes invocaciones de la función recursiva.
  2. El caso recursivo, el cual permite que una función se llame a si misma hasta toparse con el caso base.

El factorial de un número positivo es la multiplicación de ese número por el número inmediato menor y así sucesivamente hasta llegar al número 1, su notación es n!, donde nes un número positivo. Por ejemplo el factorial de 5 es 120, 5! = 5 x 4 x 3 x 2 x 1 = 120.

Entonces:

// caso base:
1! = 1 = 1
// caso recursivo, ejemplos:
2! = 2 x 1 = 2 x 1!
3! = 3 x 2 x 1 = 3 x 2!
4! = 4 x 3 x 2 x 1 = 4 x 3!
5! = 5 x 4 x 3 x 2 x 1 = 5 x 4!

Con estos datos, podemos crear nuestra formula factorial(n) = n * factorial(n-1), lo cual seria nuestro caso recursivo, pero debemos de añadir nuestro caso base para que se detenga, cuando n=1debemos obtener como resultado la unidad. Veamos como quedaría nuestra función recursiva en javascript:

See the Pen Funciones recursivas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Con esto cubrimos las cualidades principales de la programación funcional, pero recuerda, la más importante es que NO existen efectos colaterales, es decir, el uso de funciones puras.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *