JavaScript

Guia Completo de Currying e Partial Application em JavaScript

7 min de leitura

Guia Completo de Currying e Partial Application em JavaScript

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:

<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 &gt;= arity) {

return fn(...args);

}

return function(...nextArgs) {

return curried(...args, ...nextArgs);

};

};

}

// Usando com uma função comum

const multiplicar = (a, b, c) =&gt; 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, &#039;Olá&#039;);

console.log(saudacaoOla(&#039;João&#039;, &#039;Silva&#039;)); // &quot;Olá, João Silva!&quot;

const olaPara = partial(criarSaudacao, &#039;Olá&#039;, &#039;Maria&#039;);

console.log(olaPara(&#039;Costa&#039;)); // &quot;Olá, Maria Costa!&quot;</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) =&gt; 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: &#039;Ana&#039;,

saudar: function(mensagem) {

console.log(${mensagem}, ${this.nome}!);

}

};

const saudarAna = usuario.saudar.bind(usuario);

saudarAna(&#039;Bem-vindo&#039;); // &quot;Bem-vindo, Ana!&quot;</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) =&gt; (item) =&gt; {

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) =&gt; array.map(fn));

const filter = curry((predicado, array) =&gt; array.filter(predicado));

const reduce = curry((fn, inicial, array) =&gt; array.reduce(fn, inicial));

// Usando composição

const multiplicarPor2 = map(x =&gt; x * 2);

const maiorQue5 = filter(x =&gt; x &gt; 5);

const somar = reduce((a, b) =&gt; 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) =&gt; {

return regex.test(valor)

? { valido: true }

: { valido: false, erro: mensagem };

});

const validarEmail = validar(/^[\w-]+@[\w-]+\.\w+$/, &#039;Email inválido&#039;);

const validarSenha = validar(/^.{8,}$/, &#039;Senha deve ter 8+ caracteres&#039;);

console.log(validarEmail(&#039;user@example.com&#039;)); // { valido: true }

console.log(validarSenha(&#039;abc123&#039;)); // { valido: false, erro: &#039;...&#039; }</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&#039;t Know JS: Functional-Light JavaScript</a> — Guia completo sobre programação funcional em JS</li>

</ul>

Comentários

Mais em JavaScript

Eventos no DOM: addEventListener, Delegação e Propagação: Do Básico ao Avançado
Eventos no DOM: addEventListener, Delegação e Propagação: Do Básico ao Avançado

addEventListener: Fundamentos e Sintaxe O método é a forma moderna e recomend...

Como Usar Symbols, WeakMap e WeakSet em JavaScript em Produção
Como Usar Symbols, WeakMap e WeakSet em JavaScript em Produção

Symbols: Criando Identificadores Únicos Symbols são primitivos únicos em Java...

Formulários em JavaScript: Validação, Submissão e FormData: Do Básico ao Avançado
Formulários em JavaScript: Validação, Submissão e FormData: Do Básico ao Avançado

Validação de Formulários com JavaScript A validação de formulários é a primei...