在Java 8中,带有2个箭头的lambda是什么意思?
我已经阅读过几个Java 8教程。
现在我遇到了以下主题: java是否支持Currying?
在这里,我看到下面的代码:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b; System.out.println(curriedAdd.apply(1).applyAsInt(12));
我明白这个例子总结了2个元素,但我不明白这个构造:
a -> b -> a + b;
根据expression式的左边部分,该行应该执行以下function:
R apply(int value);
在此之前,我只能用一个箭头认识lambda。
如果您将其表示为非简写lambda语法或pre-lambda Java匿名类语法,则会更清楚发生了什么…
原来的问题。 为什么是两个箭头? 简单的说,定义了两个函数…第一个函数是函数定义函数,第二个函数是函数的结果,也是函数的结果。 每个都需要一个->
运算符来定义它。
非速记
IntFunction<IntUnaryOperator> curriedAdd = (a) -> { return (b) -> { return a + b; }; };
在Java 8之前的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 -> R
IntUnaryOperator
是一个函数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; } }; } };
添加括号可能会使这个更清楚:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
或者可能中间variables可能有帮助:
IntFunction<IntUnaryOperator> curriedAdd = a -> { IntUnaryOperator op = b -> a + b; return op; };
让我们用括号重写lambdaexpression式,使之更加清晰:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
所以我们正在声明一个函数,它返回一个int
。 更具体地说,返回的函数接受一个int
并返回一个int
(两个元素的和):这可以表示为一个IntUnaryOperator
。
因此, curriedAdd
是一个接受int
并返回一个IntUnaryOperator
,所以它可以表示为IntFunction<IntUnaryOperator>
。
这是两个lambdaexpression式。
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
如果你看看IntFunction
它可能会变得更清晰: IntFunction<R>
是一个FunctionalInterface
。 它表示一个函数,它接受一个int
并返回一个R
types的值。
在这种情况下,返回typesR
也是一个FunctionalInterface
,也就是一个IntUnaryOperator
。 所以第一个 (外部)函数本身返回一个函数。
在这种情况下:当应用于一个int
, curriedAdd
应该返回一个函数,再次接受一个int
(并返回int
,因为这是IntUnaryOperator
所做的)。
在函数式编程中,通常把函数的types写成param -> return_value
,你可以在这里看到。 所以curriedAdd
的types是int -> int -> int
(或者int -> (int -> int)
如果你更喜欢的话)。
Java 8的lambda语法随之而来。 要定义这样的function,你写
a -> b -> a + b
这与实际的lambda演算非常相似:
λa λb a + b
λb a + b
是采用单个参数b
并返回一个值(和)的函数。 λa λb a + b
是接受单个参数a
并返回单个参数a
另一个函数的函数。 λa λb a + b
返回λb a + b
并设置为参数值。