Что означает лямбда с 2 стрелками в Java 8?
Ранее я прочитал несколько руководств по Java 8.
Сейчас я столкнулся с следующей темой:
Поддерживает ли java Currying?
Здесь я вижу следующий код:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
Я понимаю, что этот пример суммирует 2 элемента, но я не могу понять конструкцию:
a -> b -> a + b;
В соответствии с левой частью выражения эта строка должна реализовать следующую функцию:
R apply(int value);
До этого я встречался только с лямбдами только с одной стрелкой.
Ответы
Ответ 1
Если вы выражаете это как синтаксис коротких строк лямбда или пред-лямбда-синтаксис Java-анонимного класса, то ясно, что происходит...
Оригинальный вопрос. Почему две стрелки? Простой, определены две функции... Первая функция - функция-определяющая функция, вторая - результат этой функции, которая также оказывается функцией. Для этого требуется оператор ->
.
Non-сокращенная
IntFunction<IntUnaryOperator> curriedAdd = (a) -> {
return (b) -> {
return a + b;
};
};
Предварительная Lambda перед Java 8
IntFunction<IntUnaryOperator> curriedAdd = new IntFunction<IntUnaryOperator>() {
@Override
public IntUnaryOperator apply(final int value) {
IntUnaryOperator op = new IntUnaryOperator() {
@Override
public int applyAsInt(int operand) {
return operand + value;
}
};
return op;
}
};
Ответ 2
An IntFunction<R>
- это функция int -> R
. Функция IntUnaryOperator
является функцией int -> int
.
Таким образом, IntFunction<IntUnaryOperator>
- это функция, которая принимает параметр int
as и возвращает функцию, которая принимает параметр int
as и возвращает int
.
a -> b -> a + b;
^ | |
| ---------
| ^
| |
| The IntUnaryOperator (that takes an int, b) and return an int (the sum of a and b)
|
The parameter you give to the IntFunction
Может быть, более понятно, если вы используете анонимные классы для "разложения" лямбда:
IntFunction<IntUnaryOperator> add = new IntFunction<IntUnaryOperator>() {
@Override
public IntUnaryOperator apply(int a) {
return new IntUnaryOperator() {
@Override
public int applyAsInt(int b) {
return a + b;
}
};
}
};
Ответ 3
Добавление круглых скобок может сделать это более ясным:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
Или, возможно, промежуточная переменная может помочь:
IntFunction<IntUnaryOperator> curriedAdd = a -> {
IntUnaryOperator op = b -> a + b;
return op;
};
Ответ 4
Перепишите это лямбда-выражение с круглыми скобками, чтобы сделать его более понятным:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
Итак, мы объявляем функцию, принимающую int
, которая возвращает Function
. Более конкретно, возвращаемая функция принимает значение int
и возвращает int
(сумма двух элементов): это может быть представлено как IntUnaryOperator
.
Следовательно, curriedAdd
- это функция, принимающая int
и возвращающая IntUnaryOperator
, поэтому ее можно представить как IntFunction<IntUnaryOperator>
.
Ответ 5
Это два лямбда-выражения.
IntFunction<IntUnaryOperator> curriedAdd =
a -> { //this is for the fixed value
return b -> { //this is for the add operation
return a + b;
};
}
IntUnaryOperator addTwo = curriedAdd.apply(2);
System.out.println(addTwo.applyAsInt(12)); //prints 14
Ответ 6
Если вы посмотрите IntFunction
, это может стать яснее: IntFunction<R>
- это FunctionalInterface
. Он представляет функцию, которая принимает int
и возвращает значение типа R
.
В этом случае тип возврата R
также является FunctionalInterface
, а именно IntUnaryOperator
. Таким образом, первая (внешняя) функция возвращает функцию.
В этом случае: При применении к int
предполагается, что curriedAdd
возвращает функцию, которая снова принимает int
(и возвращает снова int
, потому что это то, что делает IntUnaryOperator
).
В функциональном программировании принято писать тип функции как param -> return_value
, и вы точно видите это здесь. Таким образом, тип curriedAdd
равен int -> int -> int
(или int -> (int -> int)
, если вам это нравится).
Синтаксис Java 8 лямбда согласуется с этим. Чтобы определить такую функцию, вы пишете
a -> b -> a + b
который очень похож на фактическое лямбда-исчисление:
λa λb a + b
λb a + b
- это функция, которая принимает единственный параметр b
и возвращает значение (сумму). λa λb a + b
- это функция, которая принимает единственный параметр a
и возвращает другую функцию одного параметра. λa λb a + b
возвращает λb a + b
с a
, установленным на значение параметра.