Является ли "Partial Function Application" неправильным в контексте Javascript?

Друг мой и я обсуждали вопрос о применении карри и частичной функции в Javascript, и мы пришли к совершенно иным выводам относительно того, насколько они достижимы. Я придумал эту реализацию Function.prototype.curry, которая послужила основой для нашего обсуждения:

Function.prototype.curry = function() {
    if (!arguments.length) return this;

    var args = Array.prototype.slice.apply(arguments);
    var mmm_curry = this, args;

    return function() {
        var inner_args = Array.prototype.slice.apply(arguments);
        return mmm_curry.apply(this, args.concat(inner_args));
    }

}

Используется следующим образом:

var vindaloo = function(a, b) {
    return (a + b);
}

var karahi = vindaloo.curry(1);
var masala = karahi(2);
var gulai = karahi(3);

print(masala);
print(other);

Выходной сигнал этого в Spidermonkey следующий:

$ js curry.js
3
4

Его мнение заключалось в том, что, поскольку примитив Javascript function не поддерживает "приложение с частичной функцией", совершенно неверно ссылаться на функцию, связанную с переменной karahi, как частично применяемую. Его аргумент заключался в том, что когда функция vindaloo находится в курсе, сама функция полностью применяется и возвращается замыкание, а не "частично примененная функция".

Теперь я считаю, что, хотя сам Javascript не поддерживает поддержку частичного приложения в своих примитивах function (в отличие от ML или Haskell), это не означает, что вы не можете создать функцию более высокого порядка язык, который способен инкапсулировать понятие частично прикладной функции. Кроме того, несмотря на то, что "применяется", область действия функции все еще привязана к возвращаемому им закрытию, заставляя его оставаться "частично примененным".

Что правильно?

Ответ 1

Технически вы создаете совершенно новую функцию, которая вызывает исходную функцию. Поэтому, если мое понимание частично прикладных функций верное, это не частично применяемая функция. Частично примененная функция будет ближе к этому (обратите внимание, что это не общее решение):

vindaloo.curry = function(a) {
    return function(b) {
        return a + b;
    };
};

IIUC, это все еще не будет частично примененной функцией. Но это ближе. Истинная частично примененная функция на самом деле выглядит так, если вы можете проверить код:

function karahi(b) {
    return 1 + b;
};

Итак, технически, ваш оригинальный метод просто возвращает функцию, связанную с закрытием. Единственный способ, по-моему, частично применить функцию в JavaScript, - это проанализировать функцию, применить изменения и затем запустить ее через eval().

Однако ваше решение является хорошим практическим применением концепции для JavaScript, поэтому практически говорящий достигает цели, даже если это не является технически точным.

Ответ 2

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

Как ваша функция карри выполняет свою цель - это просто реализация подробно. Аналогичным образом мы могли бы иметь частичное применение в спецификации ECMAScript, но когда IE будет реализовывать его так же, как и вы, нет способа узнать.

Ответ 3

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

Раньше я был настолько академичен в отношении вещей, но беспокоиться о таких подробностях не получается в конечном итоге сделать настоящую работу.

Лично я использую MochiKit; он имеет хорошую функцию partial(), которая помогает в создании такого. Я люблю его.

Ответ 4

Вы должны проверить Curried JavaScript Functions. Я не полностью обернул голову вокруг своей функции карри, но у вас может получиться ваш ответ.

Изменить: я согласен с вашей оценкой, однако.

Ответ 5

По его мнению, поскольку примитив функции Javascript не поддерживает "приложение с частичной функцией"

Вы можете выглядеть элегантно в ES6:

> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]