Guia Completo de Currying e Partial Application em JavaScript Já leu

Entendendo Currying e Partial Application Currying e partial application são técnicas de programação funcional que permitem criar funções mais reutilizáveis e elegantes. Embora frequentemente confundidas, são conceitos distintos. Currying é o processo de transformar uma função que recebe múltiplos argumentos em uma sequência de funções que recebem um argumento por vez. Partial application, por sua vez, é a técnica de fixar alguns argumentos de uma função, criando uma nova função com menos parâmetros. A importância dessas técnicas vai além da sintaxe. Elas promovem composição de funções, reduzem repetição de código e facilitam a criação de abstrações poderosas. Em JavaScript, essas técnicas são particularmente valiosas para criar código mais funcional e testável. Currying: Conceito e Implementação O que é Currying? Currying transforma uma função em . Cada invocação retorna uma nova função aguardando o próximo argumento até que todos sejam fornecidos. Implementando um Curry Genérico Criar uma função auxiliar que converte qualquer função em sua versão curried é uma prática excelente:

Entendendo Currying e Partial Application

Currying e partial application são técnicas de programação funcional que permitem criar funções mais reutilizáveis e elegantes. Embora frequentemente confundidas, são conceitos distintos. Currying é o processo de transformar uma função que recebe múltiplos argumentos em uma sequência de funções que recebem um argumento por vez. Partial application, por sua vez, é a técnica de fixar alguns argumentos de uma função, criando uma nova função com menos parâmetros.

A importância dessas técnicas vai além da sintaxe. Elas promovem composição de funções, reduzem repetição de código e facilitam a criação de abstrações poderosas. Em JavaScript, essas técnicas são particularmente valiosas para criar código mais funcional e testável.

Currying: Conceito e Implementação

O que é Currying?

Currying transforma uma função f(a, b, c) em f(a)(b)(c). Cada invocação retorna uma nova função aguardando o próximo argumento até que todos sejam fornecidos.

// Função original
function somar(a, b, c) {
  return a + b + c;
}

// Função com currying
function somarCurry(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    };
  };
}

// Uso
console.log(somarCurry(1)(2)(3)); // 6

Implementando um Curry Genérico

Criar uma função auxiliar que converte qualquer função em sua versão curried é uma prática excelente:

function curry(fn) {
  const arity = fn.length; // número de parâmetros

  return function curried(...args) {
    if (args.length >= arity) {
      return fn(...args);
    }
    return function(...nextArgs) {
      return curried(...args, ...nextArgs);
    };
  };
}

// Usando com uma função comum
const multiplicar = (a, b, c) => a * b * c;
const multiplicarCurry = curry(multiplicar);

console.log(multiplicarCurry(2)(3)(4)); // 24
console.log(multiplicarCurry(2, 3)(4)); // 24 (funciona parcialmente)

A função curry calcula a aridade (número de parâmetros) da função original e retorna uma função que acumula argumentos até ter o suficiente para executar a função.

Partial Application: Fixando Argumentos

Diferença Prática entre Currying e Partial Application

Enquanto currying cria uma cadeia de funções com um argumento cada, partial application fixa alguns argumentos e retorna uma função com menos parâmetros. A distinção é fundamental para escolher a técnica correta.

// Partial application: fixar o primeiro argumento
function partial(fn, ...fixedArgs) {
  return function(...remainingArgs) {
    return fn(...fixedArgs, ...remainingArgs);
  };
}

// Exemplo prático
function criarSaudacao(saudacao, nome, sobrenome) {
  return `${saudacao}, ${nome} ${sobrenome}!`;
}

const saudacaoOla = partial(criarSaudacao, 'Olá');
console.log(saudacaoOla('João', 'Silva')); // "Olá, João Silva!"

const olaPara = partial(criarSaudacao, 'Olá', 'Maria');
console.log(olaPara('Costa')); // "Olá, Maria Costa!"

Partial Application com Bind

JavaScript oferece bind() nativamente, que é uma forma de partial application:

const dividir = (a, b) => a / b;

// Fixar o primeiro argumento como 100
const dividir100Por = dividir.bind(null, 100);
console.log(dividir100Por(4)); // 25

// Com métodos de objetos
const usuario = {
  nome: 'Ana',
  saudar: function(mensagem) {
    console.log(`${mensagem}, ${this.nome}!`);
  }
};

const saudarAna = usuario.saudar.bind(usuario);
saudarAna('Bem-vindo'); // "Bem-vindo, Ana!"

Aplicações Práticas e Composição

Currying em Callbacks e Promessas

Currying simplifica a criação de callbacks e manipuladores:

const adicionarALista = (lista) => (item) => {
  lista.push(item);
  return lista;
};

const minhaLista = [1, 2, 3];
const adicionar = adicionarALista(minhaLista);

adicionar(4);
adicionar(5);
console.log(minhaLista); // [1, 2, 3, 4, 5]

Combinando com Composição de Funções

Currying brilha quando combinado com composição funcional:

// Funções utilitárias com currying
const map = curry((fn, array) => array.map(fn));
const filter = curry((predicado, array) => array.filter(predicado));
const reduce = curry((fn, inicial, array) => array.reduce(fn, inicial));

// Usando composição
const multiplicarPor2 = map(x => x * 2);
const maiorQue5 = filter(x => x > 5);
const somar = reduce((a, b) => a + b, 0);

const numeros = [1, 2, 3, 4, 5];
const resultado = somar(maiorQue5(multiplicarPor2(numeros)));
console.log(resultado); // (4*2) + (5*2) = 18

Este padrão cria um pipeline onde cada função retorna um transformador pronto para o próximo estágio.

Caso Real: Validador com Currying

const validar = curry((regex, mensagem, valor) => {
  return regex.test(valor) 
    ? { valido: true }
    : { valido: false, erro: mensagem };
});

const validarEmail = validar(/^[\w-]+@[\w-]+\.\w+$/, 'Email inválido');
const validarSenha = validar(/^.{8,}$/, 'Senha deve ter 8+ caracteres');

console.log(validarEmail('user@example.com')); // { valido: true }
console.log(validarSenha('abc123')); // { valido: false, erro: '...' }

Conclusão

Dominado currying e partial application, você entenderá que currying decompõe funções multi-argumentos em uma sequência de funções unárias, facilitando composição e reutilização. Partial application fixa argumentos específicos, criando especializações úteis de funções genéricas. Juntas, essas técnicas são ferramentas poderosas para código funcional, testável e elegante — fundamentais para se tornar um programador JavaScript proficiente.

Referências


Artigos relacionados