51. Composición de funciones

Componer funciones consiste en usar la salida de una función como entrada de otra para construir transformaciones más complejas.

51.1 Introducción

La composición de funciones permite encadenar procesos. Primero se aplica una función y luego se usa su resultado como entrada de otra.

En programación, esta idea aparece constantemente: validar datos, normalizarlos, transformarlos, formatearlos y mostrarlos son pasos que pueden verse como funciones compuestas.

51.2 Forma general

Si tenemos dos funciones f y g, la composición de f con g se escribe así:

(f ∘ g)(x) = f(g(x))

Primero se calcula g(x). Luego ese resultado se pasa a f.

51.3 Orden de evaluación

En f(g(x)), la función que está más adentro se ejecuta primero.

x → g(x) → f(g(x))

Este orden es importante porque cambiarlo puede producir un resultado diferente.

51.4 Primer ejemplo

Definamos dos funciones simples: una suma 3 y otra duplica.

function sumarTres(x) {
  return x + 3;
}

function duplicar(x) {
  return x * 2;
}

console.log(sumarTres(5));
console.log(duplicar(5));

51.5 Componer funciones manualmente

Podemos usar la salida de una función como entrada de la otra.

function sumarTres(x) {
  return x + 3;
}

function duplicar(x) {
  return x * 2;
}

const resultado = duplicar(sumarTres(5));

console.log(resultado);

Primero se calcula sumarTres(5), que da 8. Luego se calcula duplicar(8), que da 16.

51.6 El orden importa

Componer las mismas funciones en otro orden puede cambiar el resultado.

function sumarTres(x) {
  return x + 3;
}

function duplicar(x) {
  return x * 2;
}

const primeroSumar = duplicar(sumarTres(5));
const primeroDuplicar = sumarTres(duplicar(5));

console.log(primeroSumar);
console.log(primeroDuplicar);

51.7 Notación comparada

Notación matemática Lectura En JavaScript
f(g(x)) Primero g, luego f f(g(x))
g(f(x)) Primero f, luego g g(f(x))
(f ∘ g)(x) f compuesta con g compose(f, g)(x)

51.8 Crear una función compose

Podemos crear una función que reciba dos funciones y devuelva una nueva función compuesta.

function compose(f, g) {
  return function(x) {
    return f(g(x));
  };
}

function sumarTres(x) {
  return x + 3;
}

function duplicar(x) {
  return x * 2;
}

const duplicarDespuesDeSumar = compose(duplicar, sumarTres);

console.log(duplicarDespuesDeSumar(5));

51.9 Composición con más de dos funciones

También es posible encadenar varias funciones. Cada salida alimenta la siguiente entrada.

function limpiarTexto(texto) {
  return texto.trim();
}

function pasarAMinusculas(texto) {
  return texto.toLowerCase();
}

function reemplazarEspacios(texto) {
  return texto.replaceAll(" ", "-");
}

const resultado = reemplazarEspacios(pasarAMinusculas(limpiarTexto("  Hola Mundo JS  ")));

console.log(resultado);

51.10 Crear una canalización

En programación, muchas veces se prefiere leer las transformaciones de izquierda a derecha. A este estilo se lo suele llamar canalización o pipeline.

function pipe(valor, funciones) {
  let resultado = valor;

  for (const funcion of funciones) {
    resultado = funcion(resultado);
  }

  return resultado;
}

function duplicar(x) {
  return x * 2;
}

function sumarTres(x) {
  return x + 3;
}

console.log(pipe(5, [duplicar, sumarTres]));

51.11 Composición en transformación de datos

Un flujo de datos puede verse como una composición de funciones pequeñas.

function limitar(valor) {
  return Math.max(0, Math.min(100, valor));
}

function normalizar(valor) {
  return valor / 100;
}

function porcentaje(valor) {
  return Math.round(valor * 100) + "%";
}

const valor = porcentaje(normalizar(limitar(135)));

console.log(valor);

51.12 Composición para gráficos

Al graficar, se suele convertir un valor matemático a un valor normalizado y luego a coordenadas de pantalla.

function normalizar(valor) {
  return (valor + 10) / 20;
}

function aPixeles(valorNormalizado) {
  return valorNormalizado * 400;
}

function valorAPantalla(valor) {
  return aPixeles(normalizar(valor));
}

console.log(valorAPantalla(-10));
console.log(valorAPantalla(0));
console.log(valorAPantalla(10));

51.13 Composición de transformaciones de funciones

Las transformaciones vistas en temas anteriores también pueden componerse.

g(x) = 2 · f(x - 3) + 5

En esa expresión se combinan traslación horizontal, escalado vertical y traslación vertical.

51.14 Transformación compuesta

Este ejemplo aplica varias transformaciones a una función base.

function cuadratica(x) {
  return x * x;
}

function transformada(x) {
  return 2 * cuadratica(x - 3) + 5;
}

console.log(transformada(3));
console.log(transformada(4));
console.log(transformada(5));

51.15 Composición y dominio

Para que f(g(x)) tenga sentido, el resultado de g(x) debe pertenecer al dominio de f.

Si f solo acepta valores positivos, entonces g(x) debe producir valores positivos.

En programación, esto equivale a asegurarse de que cada paso entregue datos válidos para el paso siguiente.

51.16 Validar antes de componer

Si una función espera valores positivos, conviene controlar la entrada antes de continuar.

function raiz(valor) {
  if (valor < 0) {
    return "Entrada inválida";
  }

  return Math.sqrt(valor);
}

function restarDiez(x) {
  return x - 10;
}

console.log(raiz(restarDiez(25)));
console.log(raiz(restarDiez(4)));

51.17 Composición con arreglos

Los métodos como map, filter y reduce suelen usarse como pasos de una composición de datos.

const numeros = [1, 2, 3, 4, 5, 6];

const resultado = numeros
  .filter(function(numero) {
    return numero % 2 === 0;
  })
  .map(function(numero) {
    return numero * numero;
  });

console.log(resultado);

51.18 Aplicaciones en programación

  • Construir procesos de transformación de datos.
  • Encadenar validación, normalización y formato.
  • Crear funciones nuevas a partir de funciones pequeñas.
  • Combinar transformaciones de gráficos y coordenadas.
  • Organizar código en pasos reutilizables y comprobables.

51.19 Errores comunes

  • Evaluar las funciones en el orden incorrecto.
  • Suponer que f(g(x)) y g(f(x)) siempre dan lo mismo.
  • No comprobar que la salida de una función sea entrada válida para la siguiente.
  • Crear composiciones demasiado largas y difíciles de leer.
  • Mezclar funciones con efectos secundarios cuando se esperaba una transformación simple.

51.20 Qué debes recordar de este tema

  • Componer funciones significa usar la salida de una como entrada de otra.
  • En f(g(x)), primero se calcula g(x).
  • El orden de composición puede cambiar el resultado.
  • La salida de cada función debe ser compatible con la entrada de la siguiente.
  • La composición ayuda a construir programas con transformaciones claras y reutilizables.

51.21 Conclusión

La composición de funciones permite construir operaciones complejas a partir de pasos simples. Es una idea matemática muy cercana a la programación: cada función resuelve una parte del problema y el encadenamiento define el comportamiento completo.