Descubre el poder de la programación funcional en JavaScript con técnicas avanzadas de currying y composición de funciones. Transforma tu enfoque de desarrollo con código más expresivo, reusable y mantenible.
Diagrama de composición de funciones y currying
Contenido del Artículo
Currying: Funciones Especializadas
Transforma funciones multi-argumento en secuencias de funciones unarias:
// Función normal
const sumar = (a, b, c) => a + b + c;
// Versión currificada
const sumarCurry = a => b => c => a + b + c;
// Uso
sumarCurry(2)(3)(5); // 10
// Aplicación parcial
const sumar2 = sumarCurry(2);
const sumar5 = sumar2(3);
sumar5(5); // 10
// Currying automático
const curry = (fn) => {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return (...args2) => curried.apply(this, args.concat(args2));
}
};
};
const multiplicar = (a, b, c) => a * b * c;
const multiplicarCurry = curry(multiplicar);
console.log(multiplicarCurry(2)(3)(4)); // 24
Composición de Funciones
Combina funciones simples para crear comportamientos complejos:
// Composición básica
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
// Ejemplo
const doble = x => x * 2;
const incrementar = x => x + 1;
const cuadrado = x => x ** 2;
// compose: f(g(x))
const transformar = compose(cuadrado, incrementar, doble);
transformar(3); // ((3*2)+1)**2 = 49
// pipe: g(f(x))
const transformarPipe = pipe(doble, incrementar, cuadrado);
transformarPipe(3); // ((3*2)+1)**2 = 49
pipe ejecuta de izquierda a derecha, compose de derecha a izquierda
Aplicaciones Prácticas
Implementaciones en código real:
// Validación de formularios
const validarLongitud = min => valor =>
valor.length >= min;
const validarEmail = valor =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(valor);
const crearValidador = (...validadores) => valor =>
validadores.every(validador => validador(valor));
const validarPassword = crearValidador(
validarLongitud(8),
valor => /[A-Z]/.test(valor),
valor => /[0-9]/.test(valor)
);
console.log(validarPassword('Segura123')); // true
// Transformación de datos
const usuarios = [
{ nombre: 'Ana', edad: 25 },
{ nombre: 'Carlos', edad: 30 },
{ nombre: 'María', edad: 28 }
];
const obtenerNombres = pipe(
filter(u => u.edad > 25),
map(u => u.nombre.toUpperCase()),
sort()
);
console.log(obtenerNombres(usuarios)); // ['CARLOS', 'MARÍA']
Librerías y Herramientas
Ecosistema FP en JavaScript:
Ramda
Librería FP con funciones currificadas
Lodash/fp
Versión FP de Lodash
React Hooks
Inspirados en principios FP
Redux
Flujo unidireccional inspirado en FP
// Ejemplo con Ramda
import R from 'ramda';
const usuarios = [
{ id: 1, nombre: 'Ana', edad: 25, activo: true },
{ id: 2, nombre: 'Carlos', edad: 30, activo: false },
{ id: 3, nombre: 'María', edad: 28, activo: true }
];
const nombresActivos = R.pipe(
R.filter(R.prop('activo')),
R.map(R.pipe(
R.prop('nombre'),
R.toUpper
)),
R.sortBy(R.identity)
)(usuarios);
// ['ANA', 'MARÍA']