Является ли «Приложение с частичной функцией» неправильным термином в контексте Javascript?

StackOverflow https://stackoverflow.com/questions/92984

  •  01-07-2019
  •  | 
  •  

Вопрос

Мы с моим другом обсуждали каррирование и применение частичных функций в 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), это не означает, что вы не можете создать функцию языка более высокого порядка, способную инкапсулировать концепцию частично прикладной функции.Кроме того, несмотря на «применение», область действия функции по-прежнему привязана к возвращаемому ею замыканию, в результате чего она остается «частично примененной».

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

Это было полезно?

Решение

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

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

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

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

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

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

Другие советы

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

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

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

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

Лично я использую МочиКит;у него есть хорошая функция parts(), которая помогает в его создании.Мне это нравится.

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

Редактировать:Однако я бы согласился с вашей оценкой.

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

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

> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top