Programación Funcional
Funciones puras, inmutabilidad, funciones de orden superior, currying y composición
Programación Funcional en JavaScript
La programación funcional (PF) es un paradigma que trata la computación como la evaluación de funciones matemáticas. Enfatiza la inmutabilidad, las funciones puras y el código declarativo.
Principios Fundamentales
- Funciones Puras — La misma entrada siempre produce la misma salida, sin efectos secundarios
- Inmutabilidad — Los datos nunca se modifican, solo se transforman en datos nuevos
- Funciones de Primera Clase — Las funciones son valores que se pueden pasar
- Declarativo — Describe qué hacer, no cómo hacerlo
Funciones Puras
// ❌ Impura - modifica estado externo
let total = 0;
function addToTotal(value) {
total += value; // ¡Efecto secundario!
return total;
}
// ✅ Pura - misma entrada, misma salida
function add(a, b) {
return a + b;
}
function formatUser(user) {
return `${user.firstName} ${user.lastName}`;
}
Inmutabilidad
// ❌ Mutando datos
const user = { name: "Alice", age: 30 };
user.age = 31; // ¡Mutación!
// ✅ Creando datos nuevos
const updatedUser = { ...user, age: 31 };
const newNumbers = [...numbers, 4];
// Métodos de array que retornan nuevos arrays
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((a, b) => a + b, 0);
Funciones de Orden Superior
const users = [
{ name: "Alice", age: 30 },
{ name: "Bob", age: 25 },
{ name: "Charlie", age: 35 }
];
// map - transformar cada elemento
const names = users.map(user => user.name);
// filter - mantener elementos que cumplen la condición
const adults = users.filter(user => user.age >= 30);
// reduce - acumular en un solo valor
const totalAge = users.reduce((sum, user) => sum + user.age, 0);
// Encadenamiento
const result = users
.filter(u => u.age >= 30)
.map(u => u.name)
.sort();
Composición de Funciones
const add10 = x => x + 10;
const multiply2 = x => x * 2;
const subtract5 = x => x - 5;
// Función pipe (izquierda a derecha)
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const process = pipe(
add10, // 5 + 10 = 15
multiply2, // 15 * 2 = 30
subtract5 // 30 - 5 = 25
);
process(5); // 25
Currying
// Versión curried
const curriedAdd = a => b => c => a + b + c;
curriedAdd(1)(2)(3); // 6
// Aplicación parcial
const multiply = a => b => a * b;
const double = multiply(2);
const triple = multiply(3);
[1, 2, 3].map(double); // [2, 4, 6]
[1, 2, 3].map(triple); // [3, 6, 9]
💡 Puntos Clave
- • Las funciones puras son predecibles, testeables y cacheables
- • Prefiere actualizaciones inmutables con spread y métodos de array
- • Usa map, filter, reduce para transformaciones de datos
- • Compone funciones pequeñas en pipelines más grandes
- • El currying permite aplicación parcial y funciones reutilizables