11

我和我的一个朋友正在讨论 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

他的观点是,由于 Javascriptfunction原语本身并不支持“部分函数应用”,因此将绑定到变量的函数karahi称为部分应用是完全错误的。他的论点是,当vindaloo函数被柯里化时,函数本身被完全应用并返回一个闭包,而不是“部分应用的函数”。

现在,我的观点是,虽然 Javascript 本身不支持其function原语中的部分应用程序(不像 ML 或 Haskell),但这并不意味着您不能创建该语言的高阶函数,它能够封装部分应用函数的概念。此外,尽管被“应用”,函数的范围仍然绑定到它返回的闭包,导致它保持“部分应用”。

哪个是对的?

4

5 回答 5

3

我认为谈论 JavaScript 中的偏函数应用程序是完全可以的——如果它像偏函数应用程序一样工作,那么它一定是一个。你还会怎么命名它?

你的curry函数如何实现他的目标只是一个实现细节。以类似的方式,我们可以在 ECMAScript 规范中进行部分应用,但是当 IE 像您一样实现它时,您将无法找到答案。

于 2008-09-18T14:44:55.290 回答
3

从技术上讲,您正在创建一个调用原始函数的全新函数。所以如果我对部分应用函数的理解是正确的,这不是一个部分应用函数。部分应用的函数会更接近于此(请注意,这不是通用解决方案):

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

IIUC,这仍然不是部分应用的功能。但它更接近。如果您可以检查代码,则真正的部分应用函数实际上看起来像这样:

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

因此,从技术上讲,您的原始方法只是返回一个绑定在闭包中的函数。我能想到的在 JavaScript 中真正部分应用函数的唯一方法是解析函数,应用更改,然后通过 eval() 运行它。

但是,您的解决方案是该概念在 JavaScript 中的一个很好的实际应用,因此实际上实现了目标,即使它在技术上并不准确。

于 2008-09-18T14:48:34.737 回答
1

技术细节对我来说并不重要——如果语义保持不变,并且出于所有意图和目的,该函数的行为就好像它真的是一个部分应用的函数,谁在乎呢?

我曾经对事情很学术,但担心这些细节最终并不能真正完成工作。

就个人而言,我使用MochiKit;它有一个很好的 partial() 函数,可以帮助创建这样的函数。我喜欢它。

于 2008-09-18T15:38:43.227 回答
0

您应该查看Curried JavaScript Functions。我还没有完全理解他的咖喱功能,但它可能有你的答案。

编辑:不过,我同意你的评估。

于 2008-09-18T14:43:44.887 回答
0

他的观点是,由于 Javascript 函数原语本身并不支持“部分函数应用”

你可以非常优雅地在 ES6 中进行柯里化:

> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]
于 2016-04-01T14:48:15.870 回答