在Java 8中,带有2个箭头的lambda是什么意思?

gst*_*low 118 java lambda currying java-8

我以前读了几篇Java 8教程.

现在我遇到了以下主题: java支持Currying吗?

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

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

我明白这个例子总结了2个元素,但我无法理解构造:

a -> b -> a + b;
Run Code Online (Sandbox Code Playgroud)

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

R apply(int value); 
Run Code Online (Sandbox Code Playgroud)

在此之前,我只用一支箭只遇到了lambdas.

Ada*_*dam 118

如果你把它表达为非简写lambda语法或pre-lambda Java匿名类语法,那么发生的事情会更清楚......

原来的问题.为什么是两支箭?很简单,定义了两个函数......第一个函数是函数定义函数,第二个函数是函数的结果,它也恰好是函数.每个都需要->操作员来定义它.

非速记

IntFunction<IntUnaryOperator> curriedAdd = (a) -> {
    return (b) -> {
        return a + b;
    };
};
Run Code Online (Sandbox Code Playgroud)

在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;
    }
};
Run Code Online (Sandbox Code Playgroud)

  • 是的,你是对的,但我写的仍然使用Java 8编译器,它允许你使用"有效最终"的东西 (8认同)
  • 那不是lambdas,所以人们可以得分吗?:-) (3认同)

Ale*_* C. 48

一个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
Run Code Online (Sandbox Code Playgroud)

也许更清楚的是你是否使用匿名类来"分解"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;
            }
        };
    }
};
Run Code Online (Sandbox Code Playgroud)


Tag*_*eev 29

添加括号可能会更清楚:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
Run Code Online (Sandbox Code Playgroud)

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

IntFunction<IntUnaryOperator> curriedAdd = a -> {
    IntUnaryOperator op = b -> a + b;
    return op;
};
Run Code Online (Sandbox Code Playgroud)


Tun*_*aki 24

让我们用括号重写那个lambda表达式,使其更清晰:

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
Run Code Online (Sandbox Code Playgroud)

所以我们声明一个函数,int它返回一个Function.更具体地说,返回的函数接受int并返回一个int(两个元素的总和):这可以表示为IntUnaryOperator.

因此,curriedAdd是一个带有int和返回的函数IntUnaryOperator,所以它可以表示为IntFunction<IntUnaryOperator>.


a b*_*ver 9

这是两个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
Run Code Online (Sandbox Code Playgroud)


dhk*_*hke 8

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

在这种情况下,返回类型R也是a FunctionalInterface,即a IntUnaryOperator.所以第一个(外部)函数本身返回一个函数.

在这种情况下:当应用于a时int,curriedAdd应该返回一个再次获取的函数int(并再次返回int,因为那是什么IntUnaryOperator).

在函数式编程中,通常将函数的类型编写为,param -> return_value并且您在此处可以看到.所以类型curriedAddint -> int -> int(或者int -> (int -> int)如果你更喜欢那样).

Java 8的lambda语法与此一致.要编写这样的函数,请编写

a -> b -> a + b
Run Code Online (Sandbox Code Playgroud)

这与实际的lambda演算非常相似:

?a ?b a + b
Run Code Online (Sandbox Code Playgroud)

?b a + b是一个函数,它接受一个参数b并返回一个值(总和).?a ?b a + b是一个接受单个参数a并返回单个参数的另一个函数的函数.?a ?b a + b返回?b a + ba设置该参数值.