J'ai déjà lu plusieurs tutoriels Java 8.
En ce moment, j'ai rencontré le sujet suivant: Java prend-il en charge Currying?
Ici, je vois le code suivant:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Je comprends que cet exemple somme 2 éléments mais je ne comprends pas la construction:
a -> b -> a + b;
Selon la partie gauche de l'expression, cette ligne doit implémenter la fonction suivante:
R apply(int value);
Avant cela, je ne rencontrais que des lambdas avec une seule flèche.
Réponses:
Si vous exprimez cela comme une syntaxe lambda non abrégée ou une syntaxe de classe anonyme Java pré-lambda, ce qui se passe est plus clair ...
La question originale. Pourquoi deux flèches? Simple, il y a deux fonctions en cours de définition ... La première fonction est une fonction de définition de fonction, la seconde est le résultat de cette fonction, qui se trouve également être une fonction. Chacun nécessite un
->
opérateur pour le définir.Non sténographie
Pré-Lambda avant Java 8
la source
final int value
pre-lambda
An
IntFunction<R>
est une fonctionint -> R
. AnIntUnaryOperator
est une fonctionint -> int
.Ainsi, an
IntFunction<IntUnaryOperator>
est une fonction qui prend unint
comme paramètre et renvoie une fonction qui prend unint
comme paramètre et renvoie unint
.Il est peut-être plus clair si vous utilisez des classes anonymes pour "décomposer" le lambda:
la source
L'ajout de parenthèses peut rendre cela plus clair:
Ou probablement une variable intermédiaire peut aider:
la source
Réécrivons cette expression lambda avec des parenthèses pour la rendre plus claire:
Nous déclarons donc une fonction prenant an
int
qui renvoie aFunction
. Plus précisément, la fonction retournée prend anint
et retourne anint
(la somme des deux éléments): cela peut être représenté par unIntUnaryOperator
.Par conséquent,
curriedAdd
une fonction prend-elle unint
et retourne unIntUnaryOperator
, elle peut donc être représentée parIntFunction<IntUnaryOperator>
.la source
Ce sont deux expressions lambda.
la source
Si vous regardez,
IntFunction
cela peut devenir plus clair:IntFunction<R>
est unFunctionalInterface
. Il représente une fonction qui prend unint
et retourne une valeur de typeR
.Dans ce cas, le type de retour
R
est également aFunctionalInterface
, à savoir unIntUnaryOperator
. Ainsi, la première fonction (externe) elle-même renvoie une fonction.Dans ce cas: Lorsqu'il est appliqué à un
int
,curriedAdd
est supposé retourner une fonction qui prend à nouveau anint
(et retourne à nouveauint
, car c'est ce quiIntUnaryOperator
fait).En programmation fonctionnelle, il est courant d'écrire le type d'une fonction comme
param -> return_value
et vous voyez exactement cela ici. Donc, le type decurriedAdd
estint -> int -> int
(ouint -> (int -> int)
si vous aimez mieux).La syntaxe lambda de Java 8 va de pair avec cela. Pour définir une telle fonction, vous écrivez
qui est très similaire au calcul lambda réel:
λb a + b
est une fonction qui prend un seul paramètreb
et renvoie une valeur (la somme).λa λb a + b
est une fonction qui accepte un seul paramètrea
et renvoie une autre fonction d'un seul paramètre.λa λb a + b
renvoieλb a + b
aveca
set à la valeur du paramètre.la source