Przeczytałem wcześniej kilka samouczków dotyczących języka Java 8.
W tej chwili napotkałem następujący temat: Czy java obsługuje Currying?
Tutaj widzę następujący kod:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Rozumiem, że ten przykład sumuje 2 elementy, ale nie rozumiem konstrukcji:
a -> b -> a + b;
Zgodnie z lewą częścią wyrażenia, wiersz ten powinien implementować następującą funkcję:
R apply(int value);
Wcześniej spotykałem lambdy tylko z jedną strzałką.
Odpowiedzi:
Jeśli wyrazisz to jako nieskrótową składnię lambda lub składnię anonimowych klas Java przed lambdą, będzie jaśniejsze, co się dzieje ...
Oryginalne pytanie. Dlaczego są dwie strzały? Prosto, definiowane są dwie funkcje ... Pierwsza funkcja jest funkcją definiującą funkcję, druga jest wynikiem tej funkcji, która również jest funkcją. Każdy z nich wymaga
->
zdefiniowania go przez operatora.Non-shorthand
Pre-Lambda przed Java 8
źródło
final int value
pre-lambda
Jest
IntFunction<R>
funkcjąint -> R
. JestIntUnaryOperator
funkcjąint -> int
.Zatem an
IntFunction<IntUnaryOperator>
jest funkcją, która przyjmujeint
parametr as i zwraca funkcję, która przyjmujeint
parametr as i zwraca parametrint
.Może stanie się to bardziej zrozumiałe, jeśli użyjesz klas anonimowych do „dekompozycji” lambdy:
źródło
Dodanie nawiasów może to wyjaśnić:
Lub prawdopodobnie zmienna pośrednia może pomóc:
źródło
Przepiszmy to wyrażenie lambda z nawiasami, aby było jaśniejsze:
Więc deklarujemy funkcję przyjmującą a,
int
która zwraca aFunction
. Mówiąc dokładniej, zwrócona funkcja przyjmuje anint
i zwraca anint
(sumę dwóch elementów): można to przedstawić jakoIntUnaryOperator
.Dlatego
curriedAdd
jest funkcją przyjmującąint
i zwracającą anIntUnaryOperator
, więc można ją przedstawić jakoIntFunction<IntUnaryOperator>
.źródło
To dwa wyrażenia lambda.
źródło
Jeśli spojrzysz na
IntFunction
to, może stać się jaśniejsze:IntFunction<R>
jestFunctionalInterface
. Reprezentuje funkcję, która przyjmuje anint
i zwraca wartość typuR
.W tym przypadku typem zwracanym
R
jest również aFunctionalInterface
, a mianowicie anIntUnaryOperator
. Zatem pierwsza (zewnętrzna) funkcja sama zwraca funkcję.W tym przypadku: gdy stosowane do
int
,curriedAdd
ma powrócić funkcję, która ponownie bierzeint
(i wraca ponownieint
, ponieważ to, coIntUnaryOperator
robi).W programowaniu funkcyjnym typ funkcji często zapisuje się jako
param -> return_value
i widać to dokładnie tutaj. Więc typcurriedAdd
jestint -> int -> int
(lubint -> (int -> int)
jeśli wolisz to).Towarzyszy temu składnia lambda Java 8. Aby zdefiniować taką funkcję, piszesz
co jest bardzo podobne do rzeczywistego rachunku lambda:
λb a + b
jest funkcją, która przyjmuje pojedynczy parametrb
i zwraca wartość (sumę).λa λb a + b
to funkcja, która akceptuje pojedynczy parametra
i zwraca inną funkcję pojedynczego parametru.λa λb a + b
powracaλb a + b
za
ustawieniem na wartość parametru.źródło