<h2>Entendendo Currying e Partial Application</h2>
<p>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. <strong>Currying</strong> é 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. <strong>Partial application</strong>, por sua vez, é a técnica de fixar alguns argumentos de uma função, criando uma nova função com menos parâmetros.</p>
<p>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.</p>
<h2>Currying: Conceito e Implementação</h2>
<h3>O que é Currying?</h3>
<p>Currying transforma uma função <code>f(a, b, c)</code> em <code>f(a)(b)(c)</code>. Cada invocação retorna uma nova função aguardando o próximo argumento até que todos sejam fornecidos.</p>
<pre><code class="language-javascript">// 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</code></pre>
<h3>Implementando um Curry Genérico</h3>
<p>Criar uma função auxiliar que converte qualquer função em sua versão curried é uma prática excelente:</p>
<pre><code class="language-javascript">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)</code></pre>
<p>A função <code>curry</code> 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.</p>
<h2>Partial Application: Fixando Argumentos</h2>
<h3>Diferença Prática entre Currying e Partial Application</h3>
<p>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.</p>
<pre><code class="language-javascript">// 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!"</code></pre>
<h3>Partial Application com Bind</h3>
<p>JavaScript oferece <code>bind()</code> nativamente, que é uma forma de partial application:</p>
<pre><code class="language-javascript">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!"</code></pre>
<h2>Aplicações Práticas e Composição</h2>
<h3>Currying em Callbacks e Promessas</h3>
<p>Currying simplifica a criação de callbacks e manipuladores:</p>
<pre><code class="language-javascript">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]</code></pre>
<h3>Combinando com Composição de Funções</h3>
<p>Currying brilha quando combinado com composição funcional:</p>
<pre><code class="language-javascript">// 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); // (42) + (52) = 18</code></pre>
<p>Este padrão cria um pipeline onde cada função retorna um transformador pronto para o próximo estágio.</p>
<h3>Caso Real: Validador com Currying</h3>
<pre><code class="language-javascript">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: '...' }</code></pre>
<h2>Conclusão</h2>
<p>Dominado currying e partial application, você entenderá que <strong>currying decompõe funções multi-argumentos em uma sequência de funções unárias</strong>, facilitando composição e reutilização. <strong>Partial application fixa argumentos específicos</strong>, criando especializações úteis de funções genéricas. <strong>Juntas, essas técnicas são ferramentas poderosas para código funcional, testável e elegante</strong> — fundamentais para se tornar um programador JavaScript proficiente.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Function/bind" target="_blank" rel="noopener noreferrer">MDN Web Docs - Function.prototype.bind</a></li>
<li><a href="https://javascript.info/currying-partials" target="_blank" rel="noopener noreferrer">JavaScript.info - Currying</a></li>
<li><a href="https://ramdajs.com/" target="_blank" rel="noopener noreferrer">Ramda.js Documentation</a> — Biblioteca com utilitários avançados de currying</li>
<li><a href="https://eloquentjavascript.net/05_higher_order.html" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Higher-Order Functions</a></li>
<li><a href="https://github.com/getify/Functional-Light-JS" target="_blank" rel="noopener noreferrer">You Don't Know JS: Functional-Light JavaScript</a> — Guia completo sobre programação funcional em JS</li>
</ul>