Eu li vários tutoriais de Java 8 antes.
Agora eu encontrei o seguinte tópico: Java oferece suporte ao Currying?
Aqui, vejo o seguinte código:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Eu entendo que este exemplo soma 2 elementos, mas não consigo entender a construção:
a -> b -> a + b;
De acordo com a parte esquerda da expressão, esta linha deve implementar a seguinte função:
R apply(int value);
Antes, eu só conhecia lambdas com uma flecha.
Respostas:
Se você expressar isso como sintaxe lambda não abreviada ou sintaxe de classe anônima Java pré-lambda, ficará mais claro o que está acontecendo ...
A pergunta original. Por que são duas setas? Simples, há duas funções sendo definidas ... A primeira função é uma função definidora de função, a segunda é o resultado dessa função, que também passa a ser função. Cada um requer um
->
operador para defini-lo.Não taquigrafado
Pré-Lambda antes do Java 8
fonte
final int value
pre-lambda
Um
IntFunction<R>
é uma funçãoint -> R
. UmIntUnaryOperator
é uma funçãoint -> int
.Assim, um
IntFunction<IntUnaryOperator>
é uma função que leva umint
como parâmetro e retornar uma função que leva umint
como parâmetro e retornar umint
.Talvez seja mais claro se você usar classes anônimas para "decompor" o lambda:
fonte
Adicionar parênteses pode tornar isso mais claro:
Ou provavelmente a variável intermediária pode ajudar:
fonte
Vamos reescrever essa expressão lambda com parênteses para torná-la mais clara:
Portanto, estamos declarando uma função que recebe um
int
que retorna aFunction
. Mais especificamente, a função retornada recebe umint
e retorna umint
(a soma dos dois elementos): isso pode ser representado como umIntUnaryOperator
.Portanto,
curriedAdd
é uma função que recebe umint
e retorna umIntUnaryOperator
, portanto, pode ser representada comoIntFunction<IntUnaryOperator>
.fonte
São duas expressões lambda.
fonte
Se você olhar
IntFunction
, pode ficar mais claro:IntFunction<R>
é aFunctionalInterface
. Ele representa uma função que recebe umint
e retorna um valor do tipoR
.Nesse caso, o tipo de retorno
R
também é aFunctionalInterface
, ou seja, umIntUnaryOperator
. Então o primeiro função (externa) retorna uma função.Neste caso: Quando aplicado a um
int
,curriedAdd
deve retornar uma função que novamente recebe umint
(e retorna novamenteint
, porque é isso queIntUnaryOperator
faz).Na programação funcional, é comum escrever o tipo de uma função como
param -> return_value
e você vê exatamente isso aqui. Portanto, o tipo decurriedAdd
éint -> int -> int
(ouint -> (int -> int)
se preferir, melhor).A sintaxe lambda do Java 8 vai junto com isso. Para definir tal função, você escreve
que é muito semelhante ao cálculo lambda real:
λb a + b
é uma função que recebe um único parâmetrob
e retorna um valor (a soma).λa λb a + b
é uma função que aceita um único parâmetroa
e retorna outra função de um único parâmetro.λa λb a + b
retornaλb a + b
coma
definido para o valor do parâmetro.fonte