我和我的一位朋友正在讨论Javascript中的currying和部分功能应用,我们得出的结论是否可以实现。我想出了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
函数被curry时,函数本身被完全应用并返回一个闭包,而不是“部分应用函数”。
现在,我认为虽然Javascript本身不支持部分应用程序在其function
原语中(与ML或Haskell不同),但这并不意味着您无法创建更高的顺序能够封装部分应用函数的概念的语言的功能。此外,尽管被“应用”,函数的范围仍然绑定到它返回的闭包,导致它保持“部分应用”。
哪个是对的?
答案 0 :(得分:3)
我认为谈论部分功能应用是完全可以的 在JavaScript中 - 如果它像部分应用程序一样工作,那么它必须 是一个。你怎么称呼它?
咖喱功能如何实现其目标只是一种实现 详情。以类似的方式,我们可以在ECMAScript规范中部分应用, 但是当IE会像你一样实现它时,你会有 无法找到答案。
答案 1 :(得分:3)
从技术上讲,您正在创建一个调用原始功能的全新功能。因此,如果我对部分应用函数的理解是正确的,那么这不是部分应用的函数。部分应用的函数将更接近于此(请注意,这不是一般解决方案):
vindaloo.curry = function(a) {
return function(b) {
return a + b;
};
};
IIUC,这仍然不是部分应用的功能。但它更接近。如果您可以检查代码,那么真正的部分应用函数实际上看起来像这样:
function karahi(b) {
return 1 + b;
};
因此,从技术上讲,您的原始方法 只是返回一个闭包内的函数。我能想到在JavaScript中真正部分应用函数的唯一方法是解析函数,应用更改,然后通过eval()运行它。
但是,您的解决方案是JavaScript概念的一个很好的实际应用,所以实际上说实现了目标,即使它在技术上并不精确。
答案 2 :(得分:1)
技术细节对我来说无关紧要 - 如果语义保持不变,并且出于所有意图和目的,该函数就好像它实际上是一个部分应用的函数,谁在乎呢?
我过去常常是学术事务,但担心这些细节最终无法完成真正的工作。
就个人而言,我使用MochiKit;它有一个很好的partial()函数,可以帮助创建这样的函数。我喜欢它。
答案 3 :(得分:0)
你应该看看Curried JavaScript Functions。我没有完全围绕他的咖喱功能,但它可能有你的答案。
编辑:不过,我同意你的评估。
答案 4 :(得分:0)
他的观点是,由于Javascript函数原语本身不支持“部分函数应用程序”
你可以非常优雅地在ES6中进行currying:
> const add = a => b => a + b
> const add10 = add(10)
> [1,2,3].map(add10)
[ 11, 12, 13 ]