Currying está convertendo uma única função de n argumentos em n funções com um único argumento cada. Dada a seguinte função:
function f(x,y,z) { z(x(y));}
Quando curry, torna-se:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
Para obter a aplicação completa de f (x, y, z), você precisa fazer o seguinte:
f(x)(y)(z);
Muitas linguagens funcionais permitem que você escreva f x y z
. Se você chamar apenas f x y
ou f (x) (y) , obterá uma função parcialmente aplicada - o valor de retorno é um fechamento lambda(z){z(x(y))}
com valores passados de x e y para f(x,y)
.
Uma maneira de usar aplicativos parciais é definir funções como aplicativos parciais de funções generalizadas, como fold :
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10
A maneira mais fácil de ver como elas diferem é considerar um exemplo real . Vamos assumir que temos uma função
Add
que recebe 2 números como entrada e retorna um número como saída, por exemplo,Add(7, 5)
retorna12
. Nesse caso:A aplicação parcial da função
Add
com um valor7
nos dará uma nova função como saída. Essa função em si recebe 1 número como entrada e gera um número. Assim sendo:Para que possamos fazer isso:
Currying a função
Add
nos dará uma nova função como saída. Essa função em si recebe 1 número como entrada e gera mais uma nova função. Essa terceira função recebe 1 número como entrada e retorna um número como saída. Assim sendo:Para que possamos fazer isso:
Em outras palavras, "currying" e "aplicação parcial" são duas funções totalmente diferentes. O curry requer exatamente 1 entrada, enquanto a aplicação parcial requer 2 (ou mais) entradas.
Mesmo que ambos retornem uma função como saída, as funções retornadas são de formas totalmente diferentes, como demonstrado acima.
fonte
n-ary
para(x - n)-ary
, curry den-ary
paran * 1-ary
. Uma função parcialmente aplicada possui um escopo reduzido (de aplicativo), ou seja,Add7
é menos expressivo queAdd
. Uma função ao curry, por outro lado, é tão expressiva quanto a função original.f2(7)(5) is just a syntactic shortcut
significa? (Eu sei muito pouco.) Ainda nãof2
contém / "conhece" 7?curry
implementação em algum lugar (não pense que estáfunctools
)Nota: foi extraído do F # Basics um excelente artigo introdutório para desenvolvedores .NET que ingressaram na programação funcional.
fonte
Pergunta interessante. Após algumas pesquisas, "O aplicativo de função parcial não está se recuperando" deu a melhor explicação que encontrei. Não posso dizer que a diferença prática seja particularmente óbvia para mim, mas não sou especialista em FP ...
Outra página de aparência útil (que confesso que ainda não li completamente) é "Currying and Partial Application with Java Closures" .
Parece que este é um par de termos amplamente confuso, veja bem.
fonte
Eu respondi isso em outro tópico https://stackoverflow.com/a/12846865/1685865 . Em resumo, a aplicação parcial da função consiste em corrigir alguns argumentos de uma determinada função multivariável para gerar outra função com menos argumentos, enquanto o Currying trata de transformar uma função dos argumentos N em uma função unária que retorna uma função unária ... [Um exemplo de O curry é mostrado no final deste post.]
O curry é principalmente de interesse teórico: é possível expressar cálculos usando apenas funções unárias (ou seja, todas as funções são unárias). Na prática e como subproduto, é uma técnica que pode tornar triviais muitos aplicativos funcionais parciais úteis (mas não todos), se o idioma tiver funções curry. Novamente, não é o único meio de implementar aplicativos parciais. Assim, você pode encontrar cenários em que a aplicação parcial é feita de outra maneira, mas as pessoas estão confundindo-a com curry.
(Exemplo de caril)
Na prática, não se escreveria apenas
ou o javascript equivalente
ao invés de
por uma questão de currying.
fonte
Currying é uma função de um argumento que pega uma função
f
e retorna uma nova funçãoh
. Observe queh
recebe um argumentoX
e retorna uma função que mapeiaY
paraZ
:Aplicação parcial é uma função de dois (ou mais) argumentos que levam uma função
f
e um ou mais argumentos adicionais paraf
e retornam uma nova funçãog
:A confusão surge porque, com uma função de dois argumentos, a seguinte igualdade é válida:
Ambos os lados produzirão a mesma função de um argumento.
A igualdade não é verdadeira para funções de aridade superior, porque nesse caso o curry retornará uma função de um argumento, enquanto o aplicativo parcial retornará uma função de vários argumentos.
A diferença também está no comportamento, enquanto o curry transforma toda a função original recursivamente (uma vez para cada argumento), a aplicação parcial é apenas uma substituição de uma etapa.
Fonte: Wikipedia Currying .
fonte
A diferença entre aplicação curry e aplicação parcial pode ser melhor ilustrada através deste exemplo de JavaScript a seguir:
A aplicação parcial resulta em uma função de menor aridade; no exemplo acima,
f
possui uma área de 3, enquantopartial
apenas 2. Mais importante, uma função parcialmente aplicada retornaria o resultado imediatamente ao ser chamada , e não outra função na cadeia de curry. Portanto, se você estiver vendo algo parecidopartial(2)(3)
, não é uma aplicação parcial na realidade.Leitura adicional:
fonte
Resposta simples
Curry: permite chamar uma função, dividindo-a em várias chamadas, fornecendo um argumento por chamada.
Parcial: permite chamar uma função, dividindo-a em várias chamadas, fornecendo vários argumentos por chamada.
Dicas simples
Ambos permitem que você chame uma função fornecendo menos argumentos (ou, melhor, fornecendo-os cumulativamente). Na verdade, ambos vinculam (a cada chamada) um valor específico a argumentos específicos da função.
A diferença real pode ser vista quando a função possui mais de 2 argumentos.
Simples e (c) (amostra)
(em Javascript)
por que sempre passar os argumentos, como o contexto e os retornos de chamada, se eles serão sempre os mesmos? Basta ligar alguns valores para a função
e chame-o de subject1 e foobar com
Confortável, não é? 😉
Com o curry, você precisa passar um argumento por vez
aviso Legal
Eu pulei toda a explicação acadêmica / matemática. Porque eu não sei. Talvez tenha ajudado
fonte
Eu tive essa pergunta muito enquanto aprendia e, desde então, já a fiz várias vezes. A maneira mais simples de descrever a diferença é que ambas são iguais :) Deixe-me explicar ... obviamente existem diferenças.
Tanto a aplicação parcial quanto o curry envolvem o fornecimento de argumentos para uma função, talvez não todos de uma vez. Um exemplo bastante canônico é adicionar dois números. No pseudocódigo (na verdade, JS sem palavras-chave), a função base pode ser a seguinte:
Se eu quisesse uma função "addOne", poderia aplicá-la parcialmente ou curry:
Agora, usá-los é claro:
Então qual a diferença? Bem, é sutil, mas a aplicação parcial envolve o fornecimento de alguns argumentos e a função retornada executará a função principal na próxima chamada, enquanto o currying continuará esperando até que tenha todos os argumentos necessários:
Em resumo, use o aplicativo parcial para preencher alguns valores, sabendo que na próxima vez que você chamar o método, ele será executado, deixando indefinidos todos os argumentos não fornecidos; use currying quando desejar retornar continuamente uma função parcialmente aplicada quantas vezes for necessário para cumprir a assinatura da função. Um exemplo final artificial:
Espero que isto ajude!
ATUALIZAÇÃO: Algumas implementações de linguagens ou libs permitem que você passe uma aridade (número total de argumentos na avaliação final) para a implementação parcial do aplicativo, que pode confundir minhas duas descrições em uma confusão confusa ... mas nesse momento, as duas técnicas são amplamente intercambiável.
fonte
Para mim, a aplicação parcial deve criar uma nova função na qual os argumentos usados sejam completamente integrados à função resultante.
A maioria das linguagens funcionais implementa currying retornando um fechamento: não avalie sob lambda quando parcialmente aplicada. Portanto, para que a aplicação parcial seja interessante, precisamos fazer a diferença entre currying e aplicação parcial e considerar a aplicação parcial como currying e avaliação sob lambda.
fonte
Eu poderia estar muito errado aqui, já que não tenho uma sólida formação em matemática teórica ou programação funcional, mas da minha breve incursão no FP, parece que o curry tende a transformar uma função de N argumentos em N funções de um argumento, enquanto a aplicação parcial [na prática] funciona melhor com funções variadas com um número indeterminado de argumentos. Sei que alguns dos exemplos das respostas anteriores desafiam essa explicação, mas isso me ajudou a separar os conceitos. Considere este exemplo (escrito em CoffeeScript para ser sucinto, minhas desculpas se isso for mais confuso, mas peça esclarecimentos, se necessário):
Este é obviamente um exemplo artificial, mas observe que a aplicação parcial de uma função que aceita qualquer número de argumentos nos permite executar uma função, mas com alguns dados preliminares. O curry de uma função é semelhante, mas nos permite executar uma função de parâmetro N em partes até, mas somente até, todos os parâmetros N serem contabilizados.
Novamente, esta é a minha opinião sobre as coisas que li. Se alguém discordar, eu apreciaria um comentário sobre o porquê, em vez de um voto negativo imediato. Além disso, se o CoffeeScript for difícil de ler, visite coffeescript.org, clique em "try coffeescript" e cole no meu código para ver a versão compilada, o que (espero) pode fazer mais sentido. Obrigado!
fonte
Vou assumir que a maioria das pessoas que fazem essa pergunta já está familiarizada com os conceitos básicos, portanto não há necessidade de falar sobre isso. É a sobreposição que é a parte confusa.
Você pode usar completamente os conceitos, mas os entende juntos como esse borrão conceitual amorfo pseudo-atômico. O que está faltando é saber onde está a fronteira entre eles.
Em vez de definir o que cada um é, é mais fácil destacar apenas suas diferenças - o limite.
Currying é quando você define a função.
Aplicação parcial é quando você chama a função.
Aplicação é matemática-falar para chamar uma função.
A aplicação parcial requer a chamada de uma função com curry e a obtenção de uma função como o tipo de retorno.
fonte
Existem outras ótimas respostas aqui, mas acredito que este exemplo (conforme meu entendimento) em Java pode ser benéfico para algumas pessoas:
Portanto, o currying fornece uma função de um argumento para criar funções, em que o aplicativo parcial cria uma função de invólucro que codifica um ou mais argumentos.
Se você deseja copiar e colar, o seguinte é mais barulhento, mas mais fácil de trabalhar, já que os tipos são mais brandos:
fonte
Ao escrever isso, confundi curry e uncurrying. São transformações inversas em funções. Realmente não importa o que você chama de qual, desde que você consiga o que a transformação e sua inversa representam.
Incansavelmente não é definido com muita clareza (ou melhor, existem definições "conflitantes" que capturam o espírito da idéia). Basicamente, significa transformar uma função que usa vários argumentos em uma função que usa um único argumento. Por exemplo,
Agora, como você transforma isso em uma função que requer um único argumento? Você trapaceia, é claro!
Observe que o plus agora requer um único argumento (composto de duas coisas). Super!
Qual o sentido disso? Bem, se você tem uma função que recebe dois argumentos e tem um par de argumentos, é bom saber que você pode aplicar a função aos argumentos e ainda assim obter o que espera. E, de fato, o encanamento para isso já existe, para que você não precise fazer coisas como correspondência explícita de padrões. Tudo o que tem a fazer é:
Então, o que é aplicação parcial de função? É uma maneira diferente de transformar uma função em dois argumentos em uma função com um argumento. Porém, funciona de maneira diferente. Mais uma vez, tomemos (+) como exemplo. Como podemos transformá-lo em uma função que usa um único Int como argumento? Nós trapaceamos!
Essa é a função que adiciona zero a qualquer Int.
adiciona 1 a qualquer Int. Etc. Em cada um desses casos, (+) é "parcialmente aplicado".
fonte