A programação funcional é um estilo de desenvolvimento de programa, no qual alguns recursos específicos para trabalhar com funções são amplamente utilizados. Trata-se, em particular, de transferir funções para outras funções como argumentos e de retornar funções de outras funções. O conceito de "funções puras" também pertence ao estilo funcional de programação. A saída de funções puras depende apenas da entrada; elas, quando executadas, não afetam o estado do programa.
Os princípios de programação funcional são suportados por muitos idiomas. Entre eles estão JavaScript, Haskell, Clojure, Erlang. O uso de mecanismos de programação funcional implica conhecimento, entre outros, de conceitos como funções puras, funções de curry, funções de ordem superior.

O material que estamos traduzindo hoje é sobre curry. Falaremos sobre como o curry funciona e como o conhecimento desse mecanismo pode ser útil para um desenvolvedor de JS.
O que é curry?
Currying em programação funcional é a transformação de uma função com muitos argumentos em um conjunto de funções aninhadas com um argumento. Quando uma função ao curry é chamada com um argumento passado, ela retorna uma nova função que espera que o próximo argumento chegue. Novas funções que aguardam o próximo argumento são retornadas toda vez que a função ao curry é chamada - até que a função receba todos os argumentos de que precisa. Os argumentos recebidos anteriormente, graças ao mecanismo de fechamento, aguardam o momento em que a função obtém tudo o que precisa para realizar os cálculos. Após receber o último argumento, a função executa o cálculo e retorna o resultado.
Falando em 
curry , podemos dizer que esse é o processo de transformar uma função com vários argumentos em uma função com menos aridade.
Arity é o número de argumentos para uma função. Por exemplo, aqui está a declaração de um par de funções:
function fn(a, b) {    //... } function _fn(a, b, c) {    //... } 
A função 
fn recebe dois argumentos (esta é uma função binária ou de 2 árias), a função 
_fn recebe três argumentos (uma função ternária de 3 árias).
Vamos falar sobre a situação em que, durante o currying, uma função com vários argumentos é convertida em um conjunto de funções, cada uma das quais recebe um argumento.
Considere um exemplo. Temos a seguinte função:
 function multiply(a, b, c) {   return a * b * c; } 
Leva três argumentos e retorna seu produto:
 multiply(1,2,3);  
Agora vamos pensar em como convertê-lo em um conjunto de funções, cada uma das quais recebe um argumento. Vamos criar uma versão atualizada desta função e ver como obter o mesmo resultado ao chamar várias funções:
 function multiply(a) {   return (b) => {       return (c) => {           return a * b * c       }   } } log(multiply(1)(2)(3))  
Como você pode ver, aqui convertemos a chamada em uma única função com três argumentos - 
multiply(1,2,3) na chamada em três funções - 
multiply(1)(2)(3) .
Acontece que uma função se transformou em várias funções. Ao usar a nova construção, cada função, exceto a última, retornando o resultado dos cálculos, pega um argumento e retorna outra função, também capaz de aceitar um argumento e retornar outra função. Se uma construção do formulário 
multiply(1)(2)(3) não lhe parecer muito clara, vamos escrevê-lo neste formulário para entender melhor isso:
 const mul1 = multiply(1); const mul2 = mul1(2); const result = mul2(3); log(result);  
Agora vamos alinhar por linha o que está acontecendo aqui.
Primeiro, passamos o argumento 
1 para a função 
multiply :
 const mul1 = multiply(1); 
Quando essa função funciona, esse design funciona:
 return (b) => {       return (c) => {           return a * b * c       }   } 
Agora 
mul1 tem uma referência a uma função que aceita um argumento 
b . Chamamos a função 
mul1 , passando 
2 :
 const mul2 = mul1(2); 
Como resultado dessa chamada, o seguinte código será executado:
 return (c) => {           return a * b * c       } 
A 
mul2 conterá uma referência a uma função que poderia estar nela, por exemplo, como resultado da seguinte operação:
 mul2 = (c) => {           return a * b * c       } 
Se agora chamarmos a função 
mul2 , passando-a 
3 , a função executará os cálculos necessários usando os argumentos 
b :
 const result = mul2(3); 
O resultado desses cálculos será 
6 :
 log(result) 
A função 
mul2 , que possui o nível mais alto de aninhamento, tem acesso ao escopo, aos fechamentos formados pelas 
mul1 multiply e 
mul1 . É por isso que na função 
mul2 possível executar cálculos com variáveis declaradas em funções cuja execução já foi concluída, que já retornou alguns valores e é processada pelo coletor de lixo.
Acima, examinamos um exemplo abstrato, mas, em essência, a mesma função, projetada para calcular o volume de uma caixa retangular.
 function volume(l,w,h) {   return l * w * h; } const vol = volume(100,20,90)  
Aqui está a aparência de sua versão ao curry:
 function volume(l) {   return (w) => {       return (h) => {           return l * w * h       }   } } const vol = volume(100)(20)(90)  
Portanto, o curry é baseado na seguinte idéia: com base em uma determinada função, é criada outra função que retorna uma função especializada.
Caril e uso parcial de funções
Agora, talvez, haja a sensação de que o número de funções aninhadas, ao representar uma função como um conjunto de funções aninhadas, depende do número de argumentos para a função. E se se trata de curry, então é.
Uma versão especial da função para calcular o volume, que já vimos, pode ser feita da seguinte maneira:
 function volume(l) {   return (w, h) => {       return l * w * h   } } 
Aqui as idéias são aplicadas, muito semelhantes às discutidas acima. Você pode usar esta função da seguinte maneira:
 const hV = volume(70); hV(203,142); hV(220,122); hV(120,123); 
E você pode fazer isso:
 volume(70)(90,30) 
De fato, aqui você pode ver como nós, com o comando 
volume(70) , criamos uma função especializada para calcular o volume de corpos, uma das dimensões das quais (a saber, comprimento, 
l ) é fixa. A função de 
volume espera 3 argumentos e contém 2 funções aninhadas, ao contrário da versão anterior de uma função semelhante, cuja versão ao curry continha 3 funções aninhadas.
A função que foi obtida após chamar o 
volume(70) implementa o conceito de um aplicativo de função parcial. O curry e a aplicação parcial de funções são muito semelhantes entre si, mas os conceitos são diferentes.
Em aplicação parcial, a função é transformada em outra função com menos argumentos (menos aridade). Alguns argumentos dessa função são fixos (os valores padrão são definidos para eles).
Por exemplo, existe uma função:
 function acidityRatio(x, y, z) {   return performOp(x,y,z) } 
Pode ser convertido para isso:
 function acidityRatio(x) {   return (y,z) => {       return performOp(x,y,z)   } } 
A implementação da função 
performOp() não é fornecida aqui, pois não afeta os conceitos em consideração.
A função que pode ser obtida chamando a nova função 
acidityRatio() com um argumento cujo valor precisa ser corrigido é a função original, um dos argumentos que é fixo, e essa função em si leva um argumento a menos que o original.
A versão ao curry da função terá a seguinte aparência:
 function acidityRatio(x) {   return (y) = > {       return (z) = > {           return performOp(x,y,z)       }   } } 
Como você pode ver, ao currying, o número de funções aninhadas é igual ao número de argumentos da função original. Cada uma dessas funções espera seu próprio argumento. É claro que, se a função dos argumentos não aceitar ou aceitar apenas um argumento, não poderá ser alterada.
Em uma situação em que uma função tem dois argumentos, pode-se dizer que os resultados de sua aplicação parcial e curry coincidem. Por exemplo, temos uma função:
 function div(x,y) {   return x/y; } 
Suponha que precisamos reescrevê-lo para que possamos, corrigindo o primeiro argumento, obter uma função que execute cálculos ao passar apenas o segundo argumento, ou seja, precisamos aplicar parcialmente essa função. Ficará assim:
 function div(x) {   return (y) => {       return x/y;   } } 
O resultado da curry será exatamente o mesmo.
Sobre a aplicação prática dos conceitos de curry e aplicação parcial de funções
O curry e a aplicação parcial de funções podem ser úteis em várias situações. Por exemplo, ao desenvolver pequenos módulos adequados para reutilização.
O uso parcial de funções facilita o uso de módulos universais. Por exemplo, temos uma loja online, no código da qual existe uma função usada para calcular o valor a ser pago, levando em consideração o desconto.
 function discount(price, discount) {   return price * discount } 
Existe uma certa categoria de clientes, vamos chamá-los de "clientes amados", a quem damos um desconto de 10%. Por exemplo, se esse cliente compra algo por US $ 500, oferecemos a ele um desconto de US $ 50:
 const price = discount(500,0.10); // $50 // $500 - $50 = $450 
É fácil perceber que, com essa abordagem, precisamos constantemente chamar essa função com dois argumentos:
 const price = discount(1500,0.10); // $150 // $1,500 - $150 = $1,350 const price = discount(2000,0.10); // $200 // $2,000 - $200 = $1,800 const price = discount(50,0.10); // $5 // $50 - $5 = $45 const price = discount(5000,0.10); // $500 // $5,000 - $500 = $4,500 const price = discount(300,0.10); // $30 // $300 - $30 = $270 
A função original pode ser reduzida para um formulário que permita o recebimento de novas funções com um nível de desconto predeterminado, mediante a chamada da qual é suficiente transferir o valor da compra. A função 
discount() em nosso exemplo possui dois argumentos. Aqui está como é que convertemos:
 function discount(discount) {   return (price) => {       return price * discount;   } } const tenPercentDiscount = discount(0.1); 
A função 
tenPercentDiscount() é o resultado da aplicação parcial da função 
discount() . Ao chamar 
tenPercentDiscount() dessa função, basta passar o preço e um desconto de 10%, ou seja, o argumento de 
discount , já estará definido:
 tenPercentDiscount(500); // $50 // $500 - $50 = $450 
Se houver compradores em nossa loja que decidiram dar um desconto de 20%, você poderá obter a função apropriada para trabalhar com eles assim:
 const twentyPercentDiscount = discount(0.2); 
Agora, a função 
twentyPercentDiscount() pode ser chamada para calcular o custo das mercadorias, levando em consideração um desconto de 20%:
 twentyPercentDiscount(500); // 100 // $500 - $100 = $400 twentyPercentDiscount(5000); // 1000 // $5,000 - $1,000 = $4,000 twentyPercentDiscount(1000000); // 200000 // $1,000,000 - $200,000 = $600,000 
Função universal para aplicação parcial de outras funções
Desenvolveremos uma função que aceita qualquer função e retorna sua variante, que é uma função, alguns dos argumentos já definidos. Aqui está o código que permite que você faça isso (você, se pretender desenvolver uma função semelhante, é bem possível que você obtenha outra coisa como resultado):
 function partial(fn, ...args) {   return (..._arg) => {       return fn(...args, ..._arg);   } } 
A função 
partial() aceita a função 
fn , que queremos converter na função parcialmente aplicada, e um número variável de parâmetros 
(...args ). A instrução 
rest é usada para colocar todos os parâmetros após 
fn em 
args .
Esta função retorna outra função que também aceita um número variável de parâmetros ( 
_arg ). Esta função, por sua vez, chama a função 
fn original, transmite os parâmetros 
...args e 
..._arg (usando o operador 
spread ). A função executa o cálculo e retorna o resultado.
Usamos esta função para criar uma variante da função de 
volume já familiar para você, projetada para calcular o volume de paralelepípedos retangulares, um de cujos lados é fixo:
 function volume(l,h,w) {   return l * h * w } const hV = partial(volume,100); hV(200,900); // 18000000 hV(70,60); // 420000 
Aqui você pode encontrar um exemplo de função universal para currying outras funções.
Sumário
Neste artigo, falamos sobre curry e aplicação parcial de funções. Esses métodos para transformar funções são implementados em JavaScript devido ao fechamento e ao fato de as funções em JS serem objetos da primeira classe (elas podem ser passadas como argumentos para outras funções, retornadas por elas, atribuídas a variáveis).
Caros leitores! Você usa técnicas de curry e aplicação parcial de funções em seus projetos?
