JavaScript

Dominando Currying e Partial Application em JavaScript em Projetos Reais

6 min de leitura

Dominando Currying e Partial Application em JavaScript em Projetos Reais

Currying: A Arte de Transformar Funções Currying é uma técnica que transforma uma função que aceita múltiplos argumentos em uma sequência de funções que aceitam um argumento por vez. Quando você "currifica" uma função, cada chamada retorna uma nova função que espera pelo próximo argumento até que todos sejam fornecidos. A vantagem real aparece quando você precisa reutilizar a função parcialmente. Currying permite que você crie versões especializadas sem duplicar código. Isso torna seu código mais modular e fácil de testar. Implementando um Curryificador Universal Criar um auxiliar que transforma qualquer função em sua versão currificada é essencial na prática. Aqui está uma implementação robusta: Este padrão é poderoso porque permite flexibilidade: você pode chamar com um argumento ou vários de uma vez, e ainda assim obtém o resultado correto quando todos forem fornecidos. Partial Application: Fixando Argumentos Estrategicamente Enquanto currying força uma abordagem de um argumento por vez, partial application é mais pragmática: você fixa alguns argumentos e deixa

<h2>Currying: A Arte de Transformar Funções</h2>

<p>Currying é uma técnica que transforma uma função que aceita múltiplos argumentos em uma sequência de funções que aceitam um argumento por vez. Quando você &quot;currifica&quot; uma função, cada chamada retorna uma nova função que espera pelo próximo argumento até que todos sejam fornecidos.</p>

<pre><code class="language-javascript">// Função normal

function somar(a, b, c) {

return a + b + c;

}

// Função currificada

function somarCurrificada(a) {

return function(b) {

return function(c) {

return a + b + c;

};

};

}

console.log(somarCurrificada(1)(2)(3)); // 6</code></pre>

<p>A vantagem real aparece quando você precisa reutilizar a função parcialmente. Currying permite que você crie versões especializadas sem duplicar código. Isso torna seu código mais modular e fácil de testar.</p>

<h3>Implementando um Curryificador Universal</h3>

<p>Criar um auxiliar que transforma qualquer função em sua versão currificada é essencial na prática. Aqui está uma implementação robusta:</p>

<pre><code class="language-javascript">function curry(fn) {

const arity = fn.length; // número de parâmetros esperados

return function curried(...args) {

if (args.length &gt;= arity) {

return fn(...args);

}

return (...nextArgs) =&gt; curried(...args, ...nextArgs);

};

}

// Testando com uma função real

const multiplicar = (a, b, c) =&gt; a b c;

const multiplicarCurrificada = curry(multiplicar);

console.log(multiplicarCurrificada(2)(3)(4)); // 24

console.log(multiplicarCurrificada(2, 3)(4)); // 24

console.log(multiplicarCurrificada(2)(3, 4)); // 24</code></pre>

<p>Este padrão é poderoso porque permite flexibilidade: você pode chamar com um argumento ou vários de uma vez, e ainda assim obtém o resultado correto quando todos forem fornecidos.</p>

<h2>Partial Application: Fixando Argumentos Estrategicamente</h2>

<p>Enquanto currying força uma abordagem de um argumento por vez, partial application é mais pragmática: você fixa alguns argumentos e deixa outros para depois. Não é tudo ou nada, mas uma especialização estratégica.</p>

<pre><code class="language-javascript">// Partial application manual

function dividir(a, b) {

return a / b;

}

// Fixar o divisor como 2

function dividirPorDois(a) {

return dividir(a, 2);

}

console.log(dividirPorDois(10)); // 5

// Usando bind (nativo do JavaScript)

const dividirPorTres = dividir.bind(null, 30);

console.log(dividirPorTres(2)); // 15 (30 / 2)</code></pre>

<p>A diferença sutil mas importante: currying retorna sempre uma função até ter todos os argumentos; partial application retorna o resultado assim que houver argumentos suficientes para executar.</p>

<h3>Criando um Helper de Partial Application</h3>

<p>Para maior controle e legibilidade, implemente um utilitário dedicado:</p>

<pre><code class="language-javascript">function partial(fn, ...fixedArgs) {

return function(...restArgs) {

return fn(...fixedArgs, ...restArgs);

};

}

// Aplicação prática

const lerquivo = (encoding, filePath) =&gt; Lendo ${filePath} com encoding ${encoding};

const lerUTF8 = partial(lerquivo, &#039;utf-8&#039;);

const lerLatin1 = partial(lerquivo, &#039;latin1&#039;);

console.log(lerUTF8(&#039;/arquivo.txt&#039;)); // Lendo /arquivo.txt com encoding utf-8

console.log(lerLatin1(&#039;/arquivo.txt&#039;)); // Lendo /arquivo.txt com encoding latin1</code></pre>

<p>Partial application é especialmente útil em composição de funções e callbacks, onde você precisa adaptar uma função existente sem reescrevê-la completamente.</p>

<h2>Casos de Uso Reais no Dia a Dia</h2>

<p>Na prática, essas técnicas resolvem problemas concretos. Considere um cenário comum: processar dados com funções especializadas.</p>

<pre><code class="language-javascript">// Exemplo: Processador de eventos com currying

const registrarLog = curry((nivel, modulo, mensagem) =&gt; {

console.log([${nivel}] [${modulo}] ${mensagem});

});

const logErro = registrarLog(&#039;ERRO&#039;);

const logErroAuth = logErro(&#039;AUTH&#039;);

const logErroDatabase = logErro(&#039;DATABASE&#039;);

logErroAuth(&#039;Falha na autenticação&#039;); // [ERRO] [AUTH] Falha na autenticação

logErroDatabase(&#039;Conexão perdida&#039;); // [ERRO] [DATABASE] Conexão perdida

// Exemplo: Validação com partial application

const validarEmail = (pattern, valor) =&gt; pattern.test(valor);

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

const validarEmailPadrao = partial(validarEmail, emailRegex);

console.log(validarEmailPadrao(&#039;user@example.com&#039;)); // true

console.log(validarEmailPadrao(&#039;invalid-email&#039;)); // false</code></pre>

<p>Esses padrões simplificam a criação de pipelines de transformação de dados, frameworks que precisam de callbacks customizados, e sistemas que lidam com configurações variáveis. Eles reduzem repetição de código e aumentam a reutilização.</p>

<h2>Conclusão</h2>

<p>Currying e partial application são ferramentas poderosas da programação funcional que transformam como você escreve JavaScript. <strong>Primeiro ponto</strong>: currying força uma disciplina de um argumento por vez, resultando em funções altamente reutilizáveis e componíveis. <strong>Segundo ponto</strong>: partial application oferece flexibilidade pragmática, permitindo especializar funções sem a rigidez do currying. <strong>Terceiro ponto</strong>: ambas reduzem duplicação de código e facilitam testes, sendo especialmente valiosas em arquiteturas que usam composition e higher-order functions.</p>

<p>Domine essas técnicas e você terá um código mais limpo, testável e verdadeiramente funcional.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" target="_blank" rel="noopener noreferrer">MDN Web Docs - Function</a></li>

<li><a href="https://javascript.info/currying-partials" target="_blank" rel="noopener noreferrer">JavaScript.info - Currying</a></li>

<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don&#039;t Know JS Yet - Functional Programming</a></li>

<li><a href="https://lodash.com/docs/#curry" target="_blank" rel="noopener noreferrer">Lodash - curry e partial</a></li>

<li><a href="https://eloquentjavascript.net/05_higher_order.html" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Higher-order Functions</a></li>

</ul>

Comentários

Mais em JavaScript

Como Usar Classes em JavaScript: Sintaxe, Herança e Encapsulamento em Produção
Como Usar Classes em JavaScript: Sintaxe, Herança e Encapsulamento em Produção

Fundamentos de Classes em JavaScript Classes em JavaScript são açúcar sintáti...

Como Usar Metaprogramação em JavaScript: Object.defineProperty e Decorators em Produção
Como Usar Metaprogramação em JavaScript: Object.defineProperty e Decorators em Produção

Object.defineProperty: Controle Fino sobre Propriedades Object.defineProperty...

Streams em Node.js: Leitura, Escrita e Transformação de Dados: Do Básico ao Avançado
Streams em Node.js: Leitura, Escrita e Transformação de Dados: Do Básico ao Avançado

Entendendo Streams: A Base Conceitual Streams são sequências contínuas de dad...