O que é 'Currying'?

653

Eu já vi referências a funções ao curry em vários artigos e blogs, mas não consigo encontrar uma boa explicação (ou pelo menos uma que faça sentido!)

Ben
fonte
12
[Deixado como comentário, pois será inútil para os não matemáticos.] Conforme a definição de uma categoria fechada cartesiana, existe uma família fixa de adjunções (naturalmente parametrizadas por A) entre X -> X x A e X -> X ^ A. Os isomorfismos hom (X x A, Y) <-> hom (X, Y ^ A) são as funções currye uncurryde Haskell. O importante aqui é que esses isomorfismos são corrigidos previamente e, portanto, "incorporados" à linguagem.
Alexandre C.
3
Há um bom tutorial aqui para currying em Haskell learnyouahaskell.com/higher-order-functions#curried-functions comentários curtos é que add x y = x+y(curry) é diferente add (x, y)=x+y(uncurried)
Jaider

Respostas:

872

Currying é quando você divide uma função que leva vários argumentos em uma série de funções, cada uma tendo apenas um argumento. Aqui está um exemplo em JavaScript:

function add (a, b) {
  return a + b;
}

add(3, 4); // returns 7

Esta é uma função que recebe dois argumentos, aeb, e retorna sua soma. Vamos agora curry esta função:

function add (a) {
  return function (b) {
    return a + b;
  }
}

Esta é uma função que recebe um argumento, ae retorna uma função que recebe outro argumento, b, e essa função retorna sua soma.

add(3)(4);

var add3 = add(3);

add3(4);

A primeira instrução retorna 7, como a instrução add (3, 4). A segunda instrução define uma nova função chamada add3 que adicionará 3 ao seu argumento. É o que algumas pessoas podem chamar de fechamento. A terceira instrução usa a operação add3 para adicionar 3 a 4, produzindo novamente 7 como resultado.

Kyle Cronin
fonte
236
Em um sentido prático, como posso usar esse conceito?
Strawberry
43
@Strawberry, diga, por exemplo, que você tem uma lista de números em [1, 2, 3, 4, 5]que deseja multiplicar por um número arbitrário. Em Haskell, eu posso escrever map (* 5) [1, 2, 3, 4, 5]para multiplicar a lista inteira 5e, assim, gerar a lista [5, 10, 15, 20, 25].
Nyson 26/10/2013
62
Entendo o que a função de mapa faz, mas não sei se entendi o ponto que você está tentando ilustrar para mim. Você está dizendo que a função de mapa representa o conceito de curry?
Strawberry
78
@Trawberry O primeiro argumento mapdeve ser uma função que requer apenas 1 argumento - um elemento da lista. A multiplicação - como conceito matemático - é uma operação binária; são necessários 2 argumentos. No entanto, em Haskell *é uma função ao curry, semelhante à segunda versão adddesta resposta. O resultado de (* 5)é uma função que pega um único argumento e o multiplica por 5, e que nos permite usá-lo com o mapa.
Doval
26
@Strawberry A coisa boa sobre linguagens funcionais como Standard ML ou Haskell é que você pode obter "gratuitamente". Você pode definir uma função com vários argumentos como faria em qualquer outro idioma e obterá automaticamente uma versão com caril, sem ter que usar você mesmo um monte de lambdas. Assim, você pode produzir novas funções que usam menos argumentos de qualquer função existente sem muito barulho ou incomodação, facilitando a transmissão delas para outras funções.
Doval
125

Em uma álgebra de funções, lidar com funções que recebem vários argumentos (ou um argumento equivalente que é uma N-tupla) é um tanto deselegante - mas, como Moses Schönfinkel (e, independentemente, Haskell Curry) provou, não é necessário: tudo o que você precisa. necessidade são funções que levam um argumento.

Então, como você lida com algo que naturalmente expressa como, digamos f(x,y),? Bem, você considera isso como equivalente a f(x)(y)- f(x), chame-o g, é uma função e aplica essa função a y. Em outras palavras, você só possui funções que usam um argumento - mas algumas dessas funções retornam outras funções (que também usam um argumento ;-).

Como de costume, a wikipedia tem uma boa entrada resumida sobre isso, com muitos indicadores úteis (provavelmente incluindo os que falam sobre seus idiomas favoritos ;-), além de um tratamento matemático um pouco mais rigoroso.

Alex Martelli
fonte
1
Suponho comentário semelhante ao meu acima - não vi que linguagens funcionais restrinjam funções a aceitar um único argumento. Estou enganado?
Eric M
1
@hoohoo: idiomas funcionais geralmente não restringem funções a um único argumento. No entanto, em um nível mais baixo e mais matemático, é muito mais fácil lidar com funções que levam apenas um argumento. (Em lambda cálculo, por exemplo, funções só ter um argumento de cada vez.)
Sam DeFabbia-Kane
1
ESTÁ BEM. Outras perguntas então. O seguinte é uma afirmação verdadeira? O cálculo lambda pode ser usado como modelo de programação funcional, mas a programação funcional não é necessariamente aplicada ao cálculo lambda.
Eric M
7
Como as páginas da wikipedia observam, a maioria das linguagens FP "embelezam" ou "aumentam" o cálculo lambda (por exemplo, com algumas constantes e tipos de dados) ao invés de apenas "aplicá-lo", mas não é tão próximo. BTW, o que lhe dá a impressão de que, por exemplo, Haskell NÃO "restringe funções a aceitar um único argumento"? Com certeza, embora isso seja irrelevante graças ao curry; por exemplo div :: Integral a => a -> a -> a- observe essas múltiplas setas? "Mapear a para a função mapear de a para" é uma leitura ;-). Você pode usar um argumento de tupla (único) para o div& c, mas isso seria realmente anti-idiomático em Haskell.
287 Alex Martelli
@ Alex - Wrt Haskell e arg count, eu não gastei muito tempo com Haskell, e isso foi tudo há algumas semanas atrás. Portanto, foi um erro fácil de cometer.
Eric M
101

Aqui está um exemplo concreto:

Suponha que você tenha uma função que calcula a força gravitacional que atua sobre um objeto. Se você não conhece a fórmula, pode encontrá-la aqui . Esta função aceita os três parâmetros necessários como argumentos.

Agora, estando na Terra, você só deseja calcular forças para objetos neste planeta. Em uma linguagem funcional, você pode passar a massa da Terra para a função e depois avaliar parcialmente. O que você recuperaria é outra função que usa apenas dois argumentos e calcula a força gravitacional dos objetos na Terra. Isso é chamado de curry.

Shea Daniels
fonte
2
Como curiosidade, a biblioteca Prototype para JavaScript oferece um "curry" função que faz praticamente exatamente o que você explicou aqui: prototypejs.org/api/function/curry
shuckster
Novo link da função de curry PrototypeJS. prototypejs.org/doc/latest/language/Function/prototype/curry/…
Richard Ayotte 12/12/12
7
Isso soa como aplicação parcial para mim. Meu entendimento é que, se você aplicar curry, poderá criar funções com um único argumento e compor para formar funções mais complicadas. Estou esquecendo de algo?
neontapir
9
@neontapir está correto. O que Shea descreveu não é currying. É aplicação parcial. Se uma função de três argumentos é curry e você a chama como f (1), o que você recupera não é uma função de dois argumentos. Você recebe uma função de um argumento que retorna outra função de um argumento. Uma função ao curry só pode receber um argumento. A função curry no PrototypeJS também não está curry. É aplicação parcial.
mindjuice
não (para avaliação parcial) e não (para currying). isso é conhecido como aplicação parcial. currying é necessário para habilitá-lo.
Will Ness
47

O curry é uma transformação que pode ser aplicada às funções para permitir que elas tomem um argumento a menos do que anteriormente.

Por exemplo, em F #, você pode definir uma função assim: -

let f x y z = x + y + z

Aqui a função f pega os parâmetros x, ye z e os soma juntos para que: -

f 1 2 3

Retorna 6.

De nossa definição, podemos, portanto, definir a função curry para f: -

let curry f = fun x -> f x

Onde 'fun x -> fx' é uma função lambda equivalente a x => f (x) em C #. Esta função insere a função que você deseja curry e retorna uma função que recebe um único argumento e retorna a função especificada com o primeiro argumento definido no argumento de entrada.

Usando nosso exemplo anterior, podemos obter um curry de f assim: -

let curryf = curry f

Podemos então fazer o seguinte: -

let f1 = curryf 1

O que nos fornece uma função f1 que é equivalente a f1 yz = 1 + y + z. Isso significa que podemos fazer o seguinte: -

f1 2 3

O que retorna 6.

Este processo é frequentemente confundido com 'aplicação parcial da função', que pode ser definida assim:

let papply f x = f x

Embora possamos estendê-lo a mais de um parâmetro, ou seja: -

let papply2 f x y = f x y
let papply3 f x y z = f x y z
etc.

Um aplicativo parcial pega a função e o (s) parâmetro (s) e retorna uma função que requer um ou mais parâmetros a menos, e como os dois exemplos anteriores mostram é implementado diretamente na definição da função F # padrão, para que pudéssemos obter o resultado anterior assim: -

let f1 = f 1
f1 2 3

O que retornará um resultado de 6.

Em conclusão:-

A diferença entre aplicação de função de curry e parcial é que: -

A currying pega uma função e fornece uma nova função, aceitando um único argumento e retornando a função especificada com seu primeiro argumento definido para esse argumento. Isso nos permite representar funções com vários parâmetros como uma série de funções de argumento único . Exemplo:-

let f x y z = x + y + z
let curryf = curry f
let f1 = curryf 1
let f2 = curryf 2
f1 2 3
6
f2 1 3
6

O aplicativo de função parcial é mais direto - ele pega uma função e um ou mais argumentos e retorna uma função com os primeiros n argumentos definidos para os n argumentos especificados. Exemplo:-

let f x y z = x + y + z
let f1 = f 1
let f2 = f 2
f1 2 3
6
f2 1 3
6
ljs
fonte
Portanto, os métodos em C # precisariam ser alterados antes de poderem ser parcialmente aplicados?
Cdmckay
"Isso nos permite representar funções com vários parâmetros como uma série de funções de argumento único" - perfeito, isso esclareceu tudo muito bem para mim. Obrigado
Análise difusa
44

Pode ser uma maneira de usar funções para criar outras funções.

Em javascript:

let add = function(x){
  return function(y){ 
   return x + y
  };
};

Nos permitiria chamá-lo assim:

let addTen = add(10);

Quando isso é executado, o 10é passado como x;

let add = function(10){
  return function(y){
    return 10 + y 
  };
};

o que significa que retornamos esta função:

function(y) { return 10 + y };

Então, quando você liga

 addTen();

você está realmente ligando:

 function(y) { return 10 + y };

Então, se você fizer isso:

 addTen(4)

é o mesmo que:

function(4) { return 10 + 4} // 14

Portanto, nosso addTen()sempre adiciona dez ao que quer que seja transmitido. Podemos fazer funções semelhantes da mesma maneira:

let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
let addSeventy = add(70)  // ... and so on...

Agora, a pergunta óbvia de acompanhamento é por que diabos você gostaria de fazer isso? Ele transforma o que era uma operação ansiosa x + yem uma que pode ser percorrida preguiçosamente, o que significa que podemos fazer pelo menos duas coisas: 1. operações caras em cache; 2. obter abstrações no paradigma funcional.

Imagine nossa função ao curry parecida com esta:

let doTheHardStuff = function(x) {
  let z = doSomethingComputationallyExpensive(x)
  return function (y){
    z + y
  }
}

Poderíamos chamar essa função uma vez e depois passar o resultado a ser usado em muitos lugares, o que significa que só fazemos o material computacionalmente caro uma vez:

let finishTheJob = doTheHardStuff(10)
finishTheJob(20)
finishTheJob(30)

Podemos obter abstrações de maneira semelhante.

Adzz
fonte
5
A melhor explicação passo a passo de um processo inerentemente seqüencial que eu já vi aqui, e talvez a melhor e mais explicativa resposta do lote.
4
@ jonsilver Eu diria o contrário, não é uma boa explicação. Concordo que é bom explicar o exemplo apresentado, mas as pessoas tendem a deixar de pensar: "sim, perfeitamente claro, mas eu poderia ter feito a mesma coisa de outra maneira, de que adianta curry?" Em outras palavras, eu gostaria que tivesse contexto ou explicação suficientes para iluminar não apenas como o curry funciona, mas também porque não é uma observação inútil e trivial em comparação com outras maneiras de adicionar dez.
whitneyland
29

Uma função ao curry é uma função de vários argumentos reescritos, de forma que aceita o primeiro argumento e retorna uma função que aceita o segundo argumento e assim por diante. Isso permite que funções de vários argumentos tenham alguns de seus argumentos iniciais parcialmente aplicados.

Jon Harrop
fonte
5
"Isso permite que funções de vários argumentos tenham alguns de seus argumentos iniciais parcialmente aplicados." - por que isso é benéfico?
acarlon
5
As funções do @acarlon são frequentemente chamadas repetidamente com um ou mais argumentos iguais. Por exemplo, se você quiser mapuma função fem uma lista de listas, xsspoderá fazê-lo map (map f) xss.
precisa saber é o seguinte
1
Obrigado, isso faz sentido. Eu li um pouco mais e ele se encaixou.
acarlon 5/09/13
4
Penso que esta resposta acerta de forma concisa e agradável. O "currying" é o processo de pegar a função de vários argumentos e convertê-la em uma série de funções, cada uma pegando um único argumento e retornando a função de um único argumento, ou, no caso da função final, retornando o resultado real . Isso pode ser feito automaticamente para você pelo idioma ou você pode chamar uma função curry () em outros idiomas para gerar a versão atual. Observe que chamar uma função ao curry com um parâmetro não está currying. O curry já aconteceu.
mindjuice
7

Aqui está um exemplo de brinquedo em Python:

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(Basta usar a concatenação via + para evitar distrações para programadores que não são Python.)

Edição para adicionar:

Veja http://docs.python.org/library/functools.html?highlight=partial#functools.partial , que também mostra a distinção parcial de objeto versus função na maneira como o Python implementa isso.

Anon
fonte
Eu não entendi - você faz o seguinte: >>> am_quote = curry (display_quote, "Alex Martelli"), mas depois você faz o seguinte: >>> am_quote ("currying", "Como sempre, a wikipedia possui um bom resumo. .. ") Então você tem uma função com dois argumentos. Parece que o curry deve fornecer três funções diferentes que você comporia?
Eric M
Estou usando parcial para curry apenas um parâmetro, produzindo uma função com dois argumentos. Se você quisesse, poderia extrair mais um am_quote para criar um que citasse apenas Alex sobre um assunto específico. O backgound matemático pode se concentrar em terminar com funções com apenas um parâmetro - mas acredito que fixar qualquer número de parâmetros como esse é comum (se imprecisa do ponto de vista matemático) chamado currying.
Anon
(btw - o '>>>' é o prompt no interpretador interativo do Python, não faz parte do código.)
Anon
OK, obrigado pelo esclarecimento sobre args. Eu sei sobre o Python intérprete rápido, eu estava tentando citar as linhas mas diidn't trabalho ;-)
Eric M
Após o seu comentário, procurei e encontrei outras referências, inclusive aqui no SO, à diferença entre "currying" e. "aplicação parcial" em resposta a muitas instâncias do uso impreciso com o qual estou familiarizado. Veja, por exemplo: stackoverflow.com/questions/218025/…
Anon
5

Currying está traduzindo uma função de callable f(a, b, c)para callable as f(a)(b)(c).

Caso contrário, o curry é quando você divide uma função que leva vários argumentos em uma série de funções que fazem parte dos argumentos.

Literalmente, currying é uma transformação de funções: de uma maneira de chamar para outra. Em JavaScript, geralmente criamos um wrapper para manter a função original.

O curry não chama uma função. Apenas o transforma.

Vamos criar a função curry que executa o curry para funções de dois argumentos. Em outras palavras, curry(f)para dois argumentos o f(a, b)traduz emf(a)(b)

function curry(f) { // curry(f) does the currying transform
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}

// usage
function sum(a, b) {
  return a + b;
}

let carriedSum = curry(sum);

alert( carriedSum(1)(2) ); // 3

Como você pode ver, a implementação é uma série de wrappers.

  • O resultado de curry(func)é um invólucro function(a).
  • Quando é chamado como sum(1), o argumento é salvo no Ambiente Lexical e um novo wrapper é retornado function(b).
  • Então sum(1)(2), finalmente, chama function(b)fornecendo 2, e passa a chamada para a soma multi-argumento original.
MidhunKrishna
fonte
4

Se você entende partialque está no meio do caminho. A idéia de partialé aplicar previamente argumentos a uma função e devolver uma nova função que deseja apenas os argumentos restantes. Quando essa nova função é chamada, ela inclui os argumentos pré-carregados, juntamente com os argumentos que foram fornecidos a ela.

Em Clojure +é uma função, mas para esclarecer as coisas:

(defn add [a b] (+ a b))

Você pode estar ciente de que a incfunção simplesmente adiciona 1 a qualquer número que seja passado.

(inc 7) # => 8

Vamos construí-lo usando partial:

(def inc (partial add 1))

Aqui retornamos outra função que carregou 1 no primeiro argumento de add. Como addleva dois argumentos, a nova incfunção deseja apenas o bargumento - não 2 argumentos como antes, pois 1 já foi parcialmente aplicado. Assim, partialé uma ferramenta a partir da qual criar novas funções com os valores padrão pré-fornecidos. É por isso que, em uma linguagem funcional, as funções geralmente ordenam argumentos de geral para específico. Isso facilita a reutilização de tais funções a partir das quais construir outras funções.

Agora imagine se a linguagem fosse inteligente o suficiente para entender introspectivamente que adddesejavam dois argumentos. Quando passamos para um argumento, em vez de recusar, e se a função aplicou parcialmente o argumento, passamos em nosso nome, entendendo que provavelmente pretendíamos fornecer o outro argumento posteriormente? Poderíamos então definir incsem usar explicitamente partial.

(def inc (add 1)) #partial is implied

É assim que alguns idiomas se comportam. É excepcionalmente útil quando se deseja compor funções em transformações maiores. Isso levaria um a transdutores.

Mario
fonte
3

Encontrei este artigo e o artigo que ele faz referência útil para entender melhor o curry: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

Como os outros mencionados, é apenas uma maneira de ter uma função de um parâmetro.

Isso é útil porque você não precisa assumir quantos parâmetros serão passados; portanto, você não precisa de 2, 3 e 4 funções de parâmetro.

James Black
fonte
3

Como todas as outras respostas, o curry ajuda a criar funções parcialmente aplicadas. Javascript não fornece suporte nativo para currying automático. Portanto, os exemplos fornecidos acima podem não ajudar na codificação prática. Há um exemplo excelente no código de vida (que basicamente compila com js) http://livescript.net/

times = (x, y) --> x * y
times 2, 3       #=> 6 (normal use works as expected)
double = times 2
double 5         #=> 10

No exemplo acima, quando você forneceu menos argumentos, o livescript gera uma nova função ao curry para você (duplo)

user3804449
fonte
3

O Curry pode simplificar seu código. Esse é um dos principais motivos para usar isso. Currying é um processo de conversão de uma função que aceita n argumentos em n funções que aceitam apenas um argumento.

O princípio é passar os argumentos da função passada, usando a propriedade encerramento (fechamento), para armazená-los em outra função e tratá-la como um valor de retorno, e essas funções formam uma cadeia e os argumentos finais são passados ​​para concluir a operação.

O benefício disso é que ele pode simplificar o processamento de parâmetros, lidando com um parâmetro de cada vez, o que também pode melhorar a flexibilidade e a legibilidade do programa. Isso também torna o programa mais gerenciável. Também dividir o código em partes menores tornaria o uso reutilizável.

Por exemplo:

function curryMinus(x) 
{
  return function(y) 
  {
    return x - y;
  }
}

var minus5 = curryMinus(1);
minus5(3);
minus5(5);

Eu também posso fazer ...

var minus7 = curryMinus(7);
minus7(3);
minus7(5);

Isso é ótimo para tornar o código complexo limpo e manipular métodos não sincronizados, etc.

Marcus Thornton
fonte
2

Uma função ao curry é aplicada a várias listas de argumentos, em vez de apenas uma.

Aqui está uma função regular, sem curry, que adiciona dois parâmetros Int, xey:

scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3

Aqui está uma função semelhante que é curry. Em vez de uma lista de dois parâmetros Int, você aplica esta função a duas listas de um parâmetro Int cada:

scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Intscala> second(2)
res6: Int = 3
scala> curriedSum(1)(2)
res5: Int = 3

O que está acontecendo aqui é que, quando você invoca curriedSum, você recebe duas invocações de funções tradicionais consecutivas. A primeira chamada de função usa um único parâmetro Int chamado xe retorna um valor de função para a segunda função. Esta segunda função aceita o parâmetro Int y.

Aqui está uma função chamada firstque faz em espírito o que a primeira chamada de função tradicional curriedSumfaria:

scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)(Int) => Int

A aplicação de 1 à primeira função - em outras palavras, invocando a primeira função e passando em 1 - produz a segunda função:

scala> val second = first(1)
second: (Int) => Int = <function1>

A aplicação de 2 à segunda função produz o resultado:

scala> second(2)
res6: Int = 3
nazar_art
fonte
2

Um exemplo de curry seria ao ter funções que você conhece apenas um dos parâmetros no momento:

Por exemplo:

func aFunction(str: String) {
    let callback = callback(str) // signature now is `NSData -> ()`
    performAsyncRequest(callback)
}

func callback(str: String, data: NSData) {
    // Callback code
}

func performAsyncRequest(callback: NSData -> ()) {
    // Async code that will call callback with NSData as parameter
}

Aqui, como você não conhece o segundo parâmetro para retorno de chamada ao enviá- performAsyncRequest(_:)lo, seria necessário criar outro lambda / encerramento para enviá-lo à função.

S2dent
fonte
está func callbackvoltando? Ele está sendo chamado @ callback(str)assim let callback = callback(str), callback é apenas o valor de retornofunc callback
Nikk wong
não, func callback(_:data:)aceita dois parâmetros, aqui eu só dou um, o String, então ele está aguardando o próximo ( NSData), é por isso que agora let callbackexiste outra função aguardando a
transmissão
2

Aqui está o exemplo da versão genérica e a mais curta para currying de funções com n não. de params.

const add = a => b => b ? add(a + b) : a; 

const add = a => b => b ? add(a + b) : a; 
console.log(add(1)(2)(3)(4)());

Prashant Andani
fonte
1

Aqui você pode encontrar uma explicação simples sobre a implementação de currying em C #. Nos comentários, tentei mostrar como o curry pode ser útil:

public static class FuncExtensions {
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return x1 => x2 => func(x1, x2);
    }
}

//Usage
var add = new Func<int, int, int>((x, y) => x + y).Curry();
var func = add(1);

//Obtaining the next parameter here, calling later the func with next parameter.
//Or you can prepare some base calculations at the previous step and then
//use the result of those calculations when calling the func multiple times 
//with different input parameters.

int result = func(1);
Vadim S.
fonte
1

O curry é uma das funções de ordem superior do Java Script.

Currying é uma função de muitos argumentos que são reescritos de modo que ele pegue o primeiro argumento e retorne uma função que, por sua vez, usa os argumentos restantes e retorna o valor.

Confuso?

Vamos ver um exemplo,

function add(a,b)
    {
        return a+b;
    }
add(5,6);

Isso é semelhante à seguinte função de curry,

function add(a)
    {
        return function(b){
            return a+b;
        }
    }
var curryAdd = add(5);
curryAdd(6);

Então, o que esse código significa?

Agora leia a definição novamente,

Currying é uma função de muitos argumentos que são reescritos de modo que ele pegue o primeiro argumento e retorne uma função que, por sua vez, usa os argumentos restantes e retorna o valor.

Ainda confuso? Deixe-me explicar profundamente!

Quando você chama essa função,

var curryAdd = add(5);

Ele retornará uma função como esta,

curryAdd=function(y){return 5+y;}

Portanto, isso é chamado de funções de ordem superior. Significado, invocar uma função em turnos retorna outra função é uma definição exata para a função de ordem superior. Essa é a maior vantagem da legenda, Java Script. Então volte para o curry,

Essa linha passará o segundo argumento para a função curryAdd.

curryAdd(6);

que por sua vez resulta,

curryAdd=function(6){return 5+6;}
// Which results in 11

Espero que você entenda o uso do curry aqui. Então, aproveitando as vantagens,

Por que currying?

Faz uso de reutilização de código. Menos código, menos erro. Você pode perguntar como é menos código?

Eu posso provar isso com o script ECMA 6, novas funções de seta.

Sim! ECMA 6, forneça o maravilhoso recurso chamado funções de seta,

function add(a)
    {
        return function(b){
            return a+b;
        }
    }

Com a ajuda da função de seta, podemos escrever a função acima da seguinte maneira:

x=>y=>x+y

Legal certo?

Então, menos código e menos bugs !!

Com a ajuda dessas funções de ordem superior, é possível desenvolver facilmente um código sem erros.

Eu desafio-te!

Espero que você entenda o que está currying. Por favor, sinta-se livre para comentar aqui se precisar de algum esclarecimento.

Obrigado, tenha um bom dia!

sabitha kuppusamy
fonte
0

Há um exemplo de "Currying in ReasonML".

let run = () => {
    Js.log("Curryed function: ");
    let sum = (x, y) => x + y;
    Printf.printf("sum(2, 3) : %d\n", sum(2, 3));
    let per2 = sum(2);
    Printf.printf("per2(3) : %d\n", per2(3));
  };
madeinQuant
fonte