chi*_*ro2 8 javascript functional-programming currying
假设我有一些功能:
function g(a,b,c){ return a + b + c }
Run Code Online (Sandbox Code Playgroud)
而且我想把它变成"咖喱"形式(在引文中,因为它本身并不完全是咖喱):
function h(a,b,c){
switch(true){
case (a !== undefined && b !== undefined && c !== undefined):
return a + b + c
case (a !== undefined && b !== undefined && c === undefined):
return function(c){ return a + b + c }
case (a !== undefined && b == undefined && c === undefined ):
return function(b,c){
return (c === undefined) ? function(c){ return a + b + c } : a + b + c
}
default:
return h
}
}
Run Code Online (Sandbox Code Playgroud)
上面的表单有我想要的部分绑定行为:
h(1) -> h(b,c)
h(1,2) -> h(c)
h(1,2,3) -> 6
h() -> h(a,b,c)
Run Code Online (Sandbox Code Playgroud)
现在我想将这个过程自动化为一些通用函数curry,以便给定任何未加工的函数(可能是其参数数量),生成上述函数.但我不太确定如何实现它.
或者,如果可以自动创建以下表单,那么它也很有趣:
function f(a,b,c){
return function(a){ return function(b){ return function(c){ return a + b + c }}}
}
Run Code Online (Sandbox Code Playgroud)
虽然绑定f看起来像这样:
f(1)(2)(3) = 6
Run Code Online (Sandbox Code Playgroud)
所以这是非常笨拙和非惯用的,但创建上述形式对我来说似乎更可行.
现在是否可以通过某些功能生成上述任何一种形式,如果是,如何?
我相信你可以简单地使用Function.prototype.bind.这为您提供了所需的所有灵活性,您可以立即获得函数的结果,或者只是将另一个值推入参数,直到您决定执行为止.
function sum() {
return [].reduce.call(arguments, function (c, n) {
return c + n;
});
}
sum(1, 2); //3
var sum2 = sum.bind(null, 1, 2);
sum2(); //3
var sum3 = sum2.bind(null, 3);
sum3(); //6
Run Code Online (Sandbox Code Playgroud)
您还可以使用辅助函数,如:
function curry(fn) {
var c = curry.bind(this, fn = fn.bind.apply(fn, [this].concat([].slice.call(arguments, 1))));
c.exec = fn;
return c;
}
curry(sum, 1, 2)(3)(4, 5)(6, 7, 8).exec(); //36
Run Code Online (Sandbox Code Playgroud)
此外,这是非常灵活的,因为您不必链,您可以重复使用相同的curried功能.
var sumOnePlus = curry(sum, 1);
sumOnePlus.exec(2); //3;
sumOnePlus.exec(3); //4;
Run Code Online (Sandbox Code Playgroud)