javascript - 你如何柯里化(Currying)任意数量的任何 javascript 函数?

标签 javascript functional-programming currying

假设我有一些功能:

function g(a,b,c){ return a + b + c }

我想把它变成它的“ curry ”形式(在引号中,因为它本身并不完全是 curry ):

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

    }

}

上面的形式有我想要的部分绑定(bind)行为:

h(1)     -> h(b,c)
h(1,2)   -> h(c)
h(1,2,3) -> 6
h()      -> h(a,b,c)

现在我想将这个过程自动化到一些通用函数 curry 中,这样给定任何未柯里化(Currying)的函数(可能还有它的参数数量),就会生成上述函数。但我不太确定如何实现它。

或者,如果可以自动创建以下表单,那也很有趣:

function f(a,b,c){
    return function(a){ return function(b){ return function(c){ return a + b + c }}}
}

虽然绑定(bind) f 看起来像这样:

f(1)(2)(3) = 6

所以它非常笨拙且不合惯用,但创建上述形式对我来说似乎更可行。

现在是否可以通过某些函数生成上述任何表单,如果可以,如何生成?

最佳答案

我相信您可以简单地使用 Function.prototype.bind .这为您提供了所需的所有灵 active ,无论您是想要立即获得函数的结果,还是只是将另一个值插入参数直到您决定执行。

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

您还可以使用辅助函数,例如:

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

这也非常灵活,因为您不必链接,您可以重复使用相同的柯里化(Currying)函数。

var sumOnePlus = curry(sum, 1);

sumOnePlus.exec(2); //3;
sumOnePlus.exec(3); //4;

关于javascript - 你如何柯里化(Currying)任意数量的任何 javascript 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19042221/

相关文章:

scala - 在 Scala 中,是否可以 "curry"类型的 def 参数?

function - 柯里化(Currying)一个函数以获得另一个函数 : unit -> 'a

javascript - 使用 Javascript 设置子节点的父节点类等于...?

javascript - 缺少 '()' 调用构造函数

javascript - 如何存储 Monoidal List 功能链的数据?

c++ - 奇怪的 "Could not deduce template argument for ' T'"错误

arrays - 如何链接到 Perl 6 中的内联 block ?

javascript - 仅将第二个参数绑定(bind)到 javascript 函数

javascript - 开 Jest : resolves return undefined from Promise

javascript - 级联选择: Show different options when specific options is selected