TechLead

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