我和我的一个朋友正在讨论 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然后像您一样实现它时,您将无法找出答案。

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

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

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

你应该检查一下 柯里化 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