带两个箭头的 lambda 在 Java8中是什么意思?

我以前读过几篇 Java8教程。

现在我遇到了以下话题: Java 支持 Curry 吗?

在这里,我看到以下代码:

IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));

I understand that this example sum 2 elements but I cannot understand the construction:

a -> b -> a + b;

根据表达式的左半部分,此行应实现以下功能:

R apply(int value);

在此之前,我只用一支箭见过 Lambda。

15994 次浏览

如果您将其表示为非简写的 lambda 语法或者 lambda 之前的 Java 匿名类语法,那么会发生什么就更清楚了..。

最初的问题。为什么是两支箭?很简单,有两个函数正在被定义... ... 第一个函数是一个函数定义函数,第二个函数是该函数的结果,它也恰好是函数。每个都需要一个 ->运算符来定义它。

非速记

IntFunction<IntUnaryOperator> curriedAdd = (a) -> {
return (b) -> {
return a + b;
};
};

Java8之前的预 Lambda

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;
}
};

IntFunction<R>是函数 int -> RIntUnaryOperator是函数 int -> int

因此,IntFunction<IntUnaryOperator>是一个以 int为参数并返回以 int为参数并返回 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

如果使用匿名类来“分解”lambda,也许会更清楚:

IntFunction<IntUnaryOperator> add = new IntFunction<IntUnaryOperator>() {
@Override
public IntUnaryOperator apply(int a) {
return new IntUnaryOperator() {
@Override
public int applyAsInt(int b) {
return a + b;
}
};
}
};

让我们重写带括号的 lambda 表达式,让它更清晰:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

因此,我们声明一个函数,使用返回 Functionint。更具体地说,返回的函数接受一个 int并返回一个 int(两个元素的和) : 这可以表示为一个 IntUnaryOperator

Therefore, curriedAdd is a function taking an int and returning an IntUnaryOperator, so it can be represented as IntFunction<IntUnaryOperator>.

加上括号可能会使这一点更加清楚:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

或者中间变量可能会有所帮助:

IntFunction<IntUnaryOperator> curriedAdd = a -> {
IntUnaryOperator op = b -> a + b;
return op;
};

如果你看看 IntFunction,它可能会变得更清楚: IntFunction<R>是一个 FunctionalInterface。它表示一个接受 int并返回 R类型值的函数。

在这种情况下,返回类型 R也是 FunctionalInterface,即 IntUnaryOperator。因此,first(外部)函数本身返回一个函数。

在这种情况下: 当应用到 int时,curriedAdd应该返回一个再次接受 int的函数(并再次返回 int,因为 IntUnaryOperator就是这么做的)。

在函数式编程中,通常将函数的类型写成 param -> return_value,您在这里可以看到这一点。所以 curriedAdd的类型是 int -> int -> int(或者 int -> (int -> int),如果你更喜欢它的话)。

Java8的 lambda 语法也是如此

a -> b -> a + b

which is very much similar to actual lambda calculus:

λa λb a + b

λb a + b是一个函数,它接受一个参数 b并返回一个值(和)。λa λb a + b是一个接受单个参数 a并返回单个参数的另一个函数的函数。λa λb a + b返回 λb a + b,将 a设置为参数值。

这是两个 lambda 表达式。

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