What does lambda with 2 arrows mean in Java 8?

Solution 1:

If you express this as non-shorthand lambda syntax or pre-lambda Java anonymous class syntax it is clearer what is happening...

The original question. Why are two arrows? Simple, there are two functions being defined... The first function is a function-defining-function, the second is the result of that function, which also happens to be function. Each requires an -> operator to define it.

Non-shorthand

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

Pre-Lambda before 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;
    }
};

Solution 2:

An IntFunction<R> is a function int -> R. An IntUnaryOperator is a function int -> int.

Thus an IntFunction<IntUnaryOperator> is a function that takes an int as parameter and return a function that takes an int as parameter and return an 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

Maybe it is more clear if you use anonymous classes to "decompose" the 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;
            }
        };
    }
};

Solution 3:

Adding parentheses may make this more clear:

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

Or probably intermediate variable may help:

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