Раньше я читал несколько руководств по Java 8.
Прямо сейчас я столкнулся со следующей темой: поддерживает ли Java каррирование?
Здесь я вижу следующий код:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Я понимаю, что этот пример суммирует 2 элемента, но я не могу понять конструкцию:
a -> b -> a + b;
Согласно левой части выражения, эта строка должна выполнять следующую функцию:
R apply(int value);
До этого я встречал лямбды только с одной стрелкой.
Ответы:
Если вы выразите это как не сокращенный синтаксис лямбда или синтаксис анонимного класса Java до лямбда, это станет более ясным, что происходит ...
Исходный вопрос. Почему две стрелки? Проще говоря, здесь определяются две функции ... Первая функция - это функция, определяющая функцию, вторая - результат этой функции, которая также является функцией. Каждый требует, чтобы
->
оператор определил его.Non-стенография
Pre-Lambda до Java 8
источник
final int value
pre-lambda
An
IntFunction<R>
- это функцияint -> R
. AnIntUnaryOperator
- это функцияint -> int
.Таким образом, an
IntFunction<IntUnaryOperator>
- это функция, которая принимаетint
параметр as и возвращает функцию, которая принимаетint
параметр as и возвращаетint
.Может быть, будет более понятно, если вы используете анонимные классы для «разложения» лямбда:
источник
Добавление скобок может прояснить это:
Или, возможно, может помочь промежуточная переменная:
источник
Давайте перепишем это лямбда-выражение в круглые скобки, чтобы было понятнее:
Итак, мы объявляем функцию, принимающую,
int
которая возвращаетFunction
. В частности, возвращаемая функция принимаетint
и возвращаетint
(сумму двух элементов): это может быть представлено какIntUnaryOperator
.Следовательно,
curriedAdd
это функция, принимающаяint
и возвращающаяIntUnaryOperator
, поэтому ее можно представить какIntFunction<IntUnaryOperator>
.источник
Это два лямбда-выражения.
источник
Если посмотреть,
IntFunction
может стать яснее:IntFunction<R>
это файлFunctionalInterface
. Он представляет функцию, которая принимаетint
и возвращает значение типаR
.В этом случае возвращаемый тип
R
также является aFunctionalInterface
, а именноIntUnaryOperator
. Итак, первая (внешняя) функция сама возвращает функцию.В этом случае: при применении к
int
,curriedAdd
предполагается, что возвращает функцию, которая снова принимаетint
(и снова возвращаетint
, потому что это то, чтоIntUnaryOperator
делает).В функциональном программировании принято писать тип функции как,
param -> return_value
и вы видите именно это здесь. Так что типcurriedAdd
естьint -> int -> int
(или,int -> (int -> int)
если вам так больше нравится).Лямбда-синтаксис Java 8 соответствует этому. Чтобы определить такую функцию, вы пишете
что очень похоже на реальное лямбда-исчисление:
λb a + b
- это функция, которая принимает один параметрb
и возвращает значение (сумму).λa λb a + b
- это функция, которая принимает один параметрa
и возвращает другую функцию от одного параметра.λa λb a + b
возвращаетсяλb a + b
сa
установленным значением параметра.источник