Что означает лямбда с 2 стрелками в Java 8?



Я читал несколько Java 8 учебники раньше.



прямо сейчас я столкнулся со следующей темой:
поддерживает ли java карринг?



здесь, я вижу следующий код:



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


Я понимаю, что этот пример суммирует 2 элемента, но я не могу понять конструкцию:



a -> b -> a + b;


согласно левой части выражения, эта строка должна реализовывать следующую функцию:



R apply(int value); 


до этого я встречался только с лямбдами с одной стрелой.

546   6  

6 ответов:

Если вы выражаете это как не стенографический синтаксис лямбда или синтаксис анонимного класса Java pre-lambda, то становится яснее, что происходит...

исходный вопрос. Почему две стрелы? Просто, есть две функции, которые определяются... Первая функция-это функция, определяющая функцию, вторая-результат этой функции, которая также является функцией. Каждый требует -> оператор для его определения.

Не стенография

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

Лямбда-Выражения до 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;
    }
};

An 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

может быть, это более ясно, если вы используете анонимные классы для "разложения" лямбда:

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

или, вероятно, промежуточная переменная может помочь:

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

давайте перепишем это лямбда-выражение со скобками, чтобы сделать его более ясным:

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

Итак, мы объявляем функцию, принимающую int который возвращает a Function. Более конкретно, возвращаемая функция принимает значение int и возвращает int (сумма двух элементов): это может быть представлен как IntUnaryOperator.

таким образом, curriedAdd это функция, принимающая int и возврат IntUnaryOperator, поэтому его можно представить как IntFunction<IntUnaryOperator>.

Это два лямбда-выражения.

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.

в этом случае тип возвращаемого 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 установите значение параметра.

Comments

    Ничего не найдено.