Являются ли цепочечные методы, которые требуют только одного параметра на метод, эквивалентными каррированию?

15

В последнее время я играю с Ruby, и мне стало интересно, если в чистых объектно-ориентированных языках (и даже в тех, которые не являются чистыми) создание методов, которые принимают только один параметр, а затем объединяются в цепочки, эквивалентно каррированию в языках с функционалом стиль? Если нет, то почему нет? Буду признателен за подробный, даже строгий ответ по этому вопросу.

Мировой инженер
источник

Ответы:

14

Цепочка методов в объектно-ориентированных языках немного отличается от каррирования. По определению , результат каррирования является более ограниченной формой исходной функции . По соглашению , результатом цепочки методов является измененная форма исходного (обычно не функционального) объекта . Цепочка методов может использоваться с несвязанными методами в одном и том же классе, тогда как каррирование возвращает функцию, в которой один или несколько параметров исходной функции являются фиксированными (предопределенными).

В Java цепочка методов выглядит так:

String myString = new StringBuilder("Hi ").append(firstName)
                                          .append(" ")
                                          .append(lastName)
                                          .append("!")
                                          .toString();

Таким образом, каждый из этих вызовов метода .append () возвращает указатель на анонимный объект StringBuilder. Этот объект завершается после каждого .append (), и это не функция.

Напротив, в Scala частичное применение или карри выглядит так:

def simple(x:Int, y:Int, z:Int) = x * (y + z)
val simpler = simple(2, _:Int, _:Int)
simpler(3, 4) => 14

(Образец взят из блога Даниила Янковского )

simpler()в этом примере это функция-обертка для simple(). simpler()это все еще функция, которая принимает больше параметров, прежде чем она может вычислить что-либо, кроме более ограниченной версии самой себя.

РЕДАКТИРОВАТЬ: Чтение этого днем ​​позже, я думаю, что «функция-обертка» является ключом. Каррирование или частичное применение лучше всего имитировать в Java с помощью методов-оболочек.

public interface Simpler {
    public int apply(int y, int z);
}

public class Simple {
    public int apply(int x, int y, int z) { return x * (y + z); }

    public Simpler partiallyApply(final int x) {
        final simple = this;
        return new Simpler() {
            @Override
            public int apply(int y, int z) {
                // x is the final int parameter to partiallyApply()
                simple.apply(x, y, z);
            }
        }
    }
}

: END-EDIT

Цепочка методов может быть аналогична частичному применению или карри, но она может быть эквивалентна только методам, которые возвращают другие методы (ищите Функторы), и тогда методы должны быть настроены с типами возврата, которые осмысленно моделируют каррирование или частичное применение.

Цепочка методов чаще используется для реализации чего-то вроде ленивых вычислений, как это делается с помощью шаблона проектирования «Builder» и новых интерфейсов библиотеки коллекций в Java 8 .

Надеюсь, это поможет.

GlenPeterson
источник
+1: я знал это, но я не думаю, что мог бы сформулировать это так близко, как вы.
Питер Роуэлл
Хорошо объяснено, вот зеленая галочка и голос за вашу неприятность.
Мировой инженер
Вопрос об очень хорошем примере StringBuilder - toString()разве мы без вызова не будем эффективно повторять намерение каррирования в нашем вызове? Я просто пытаюсь понять концепцию карри в ОО.
Шридхар Сарнобат
1
@ Sridhar-Sarnobat функция карри возвращает другую функцию с меньшим количеством параметров. Исключенные параметры превращаются во внутренние константы в возвращаемой функции. Некоторые объекты обрабатываются как функции в Java 8, что может сбивать с толку, но StringBuilder не является одним из них. Хм, внутри StringBuilder append(charSeq)функция является каррированной формой insert(destOffset, charSeq)функции, где destOffsetвсегда длина StringBuilder.
ГленПетерсон