你如何讨论任意arity的任何javascript函数?

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)

所以这是非常笨拙和非惯用的,但创建上述形式对我来说似乎更可行.

现在是否可以通过某些功能生成上述任何一种形式,如果是,如何?

pla*_*alx 5

我相信你可以简单地使用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)