Autant que je sache, il n'y a que deux types de fonctions, destructives et constructives.
Alors que la fonction constructive, comme son nom l'indique, construit quelque chose, une fonction destructrice détruit quelque chose, mais pas de la manière que vous pensez actuellement.
Par exemple, la fonction
Function<Integer,Integer> f = (x,y) -> x + y
est une question constructive . Comme vous avez besoin de construire quelque chose. Dans l'exemple, vous avez construit le tuple (x, y) . Les fonctions constructives ont le problème de ne pas pouvoir gérer des arguments infinis. Mais le pire, c'est que vous ne pouvez pas simplement laisser une dispute ouverte. Vous ne pouvez pas simplement dire "eh bien, laissez x: = 1" et essayer chaque y que vous voudrez peut-être essayer. Vous devez construire à chaque fois le tuple entier avec
x := 1
. Donc, si vous aimez voir ce que les fonctions renvoient, y := 1, y := 2, y := 3
vous devez écrire f(1,1) , f(1,2) , f(1,3)
.
Dans Java 8, les fonctions constructives doivent être gérées (la plupart du temps) en utilisant des références de méthode car il n'y a pas beaucoup d'avantages à utiliser une fonction lambda constructive. Ce sont un peu comme des méthodes statiques. Vous pouvez les utiliser, mais ils n'ont aucun état réel.
L'autre type est le destructeur, il prend quelque chose et le démonte autant que nécessaire. Par exemple, la fonction destructive
Function<Integer, Function<Integer, Integer>> g = x -> (y -> x + y)
fait la même chose que la fonction f
qui était constructive. Les avantages d'une fonction destructive sont que vous pouvez désormais gérer des arguments infinis, ce qui est particulièrement pratique pour les flux, et vous pouvez simplement laisser les arguments ouverts. Donc, si vous voulez à nouveau voir à quoi ressemblerait le résultat si x := 1
et y := 1 , y := 2 , y := 3
, vous pouvez dire h = g(1)
et
h(1)
est le résultat pour y := 1
, h(2)
pour y := 2
et h(3)
pour y := 3
.
Vous avez donc ici un état fixe! C'est assez dynamique et c'est la plupart du temps que ce que l'on attend d'un lambda.
Les modèles comme Factory sont beaucoup plus faciles si vous pouvez simplement ajouter une fonction qui fait le travail pour vous.
Les destructeurs se combinent facilement les uns avec les autres. Si le type est correct, vous pouvez simplement les composer comme vous le souhaitez. En utilisant cela, vous pouvez facilement définir des morphismes qui facilitent (avec des valeurs immuables) les tests!
Vous pouvez le faire aussi avec une composition constructive, mais la composition destructive ressemble plus à une liste ou à un décorateur, et la composition constructive ressemble beaucoup à un arbre. Et des choses comme le retour en arrière avec des fonctions constructives ne sont tout simplement pas agréables. Vous pouvez simplement sauvegarder les fonctions partielles d'une fonction destructive (programmation dynamique), et en "retour arrière", utilisez simplement l'ancienne fonction destructive. Cela rend le code beaucoup plus petit et plus lisible. Avec les fonctions constructives, vous avez plus ou moins à vous souvenir de tous les arguments, ce qui peut être beaucoup.
Alors, pourquoi y a-t-il un besoin de BiFunction
devrait être plus question que pourquoi il n'y en a pas TriFunction
?
Tout d'abord, la plupart du temps, vous n'avez que quelques valeurs (moins de 3) et n'avez besoin que d'un résultat, donc une fonction destructive normale ne serait pas du tout nécessaire, une fonction constructive ferait bien l'affaire. Et il y a des choses comme les monades qui ont vraiment besoin d'une fonction constructive. Mais à part ça, il n'y a pas vraiment beaucoup de bonnes raisons pour lesquelles il y en a BiFunction
du tout. Ce qui ne veut pas dire qu'il devrait être supprimé! Je me bats pour mes Monades jusqu'à ma mort!
Donc, si vous avez beaucoup d'arguments, que vous ne pouvez pas combiner dans une classe de conteneur logique, et si vous avez besoin que la fonction soit constructive, utilisez une référence de méthode. Sinon, essayez d'utiliser la nouvelle capacité acquise des fonctions destructrices, vous pourriez vous retrouver à faire beaucoup de choses avec beaucoup moins de lignes de code.