javascript - 柯里化(Currying)一个接受无限参数的函数

标签 javascript functional-programming

使用 ES5,如何柯里化(Currying)一个接受无限参数的函数。

function add(a, b, c) {
    return a + b + c;
}

上面的函数只接受三个参数,但我们希望柯里化(Currying)版本能够接受无限个参数。

因此,以下所有测试用例都应该通过:

var test = add(1);

test(2);     //should return 3
test(2,3);   //should return 6
test(4,5,6); //should return 16

这是我想出的解决方案:

function add(a, b, c) {
    var args = Array.prototype.slice.call(arguments);

    return function () {
        var secondArgs = Array.prototype.slice.call(arguments);
        var totalArguments = secondArgs.concat(args);

        var sum = 0;

        for (i = 0; i < totalArguments.length; i++) {
            sum += totalArguments[0];
        }

        return sum;
    }
}

但是,有人告诉我它的风格不是很“实用”。

最佳答案

add 函数不是很“实用”的部分原因是它试图做的不仅仅是将传递给它的数字相加。如果其他开发人员查看您的代码,看到一个 add 函数,当他们调用它时,得到一个返回给他们的函数而不是求和,这会让其他开发人员感到困惑。

例如:

//Using your add function, I'm expecting 6
add(1,2,3) //Returns another function = confusing!

函数式方法

函数式方法是创建一个允许您柯里化(Currying)任何其他函数的函数,并简化您的添加函数:

function curry(fn) {
    var args = Array.prototype.slice.call(arguments, 1);

    return function () {
        return fn.apply(this, args.concat(
                Array.prototype.slice.call(arguments, 0)
        ));
    }
}

function add() {
    var args = Array.prototype.slice.call(arguments);

    return args.reduce(function (previousValue, currentValue) {
        return previousValue + currentValue;
    });
}

现在,如果你想柯里化(Currying)这个函数,你只需要做:

var curry1 = curry(add, 1);
console.log(
        curry1(2), // Logs 3
        curry1(2, 3), // Logs 6
        curry1(4, 5, 6) // Logs 16
);

//You can do this with as many arguments as you want
var curry15 = curry(add, 1,2,3,4,5);
console.log(curry15(6,7,8,9)); // Logs 45

如果我仍然想添加 1, 2, 3 我可以这样做:

add(1,2,3) //Returns 6, AWESOME!

继续功能方法

此代码现在可以从任何地方重用。

您可以使用该 curry 函数来创建其他 curry 函数引用,而无需任何额外的麻烦。

坚持数学主题,假设我们有一个乘法函数,将传递给它的所有数字相乘:

function multiply() {
    var args = Array.prototype.slice.call(arguments);

    return args.reduce(function (previousValue, currentValue) {
        return previousValue * currentValue;
    });
}

multiply(2,4,8) // Returns 64

var curryMultiply2 = curry(multiply, 2);
curryMultiply2(4,8) // Returns 64

这种函数式柯里化(Currying)方法允许您将这种方法用于任何函数,而不仅仅是数学函数。虽然提供的 curry 函数并不支持所有边缘情况,但它为您的问题提供了一个实用、简单的解决方案,可以轻松构建。

关于javascript - 柯里化(Currying)一个接受无限参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35039020/

相关文章:

javascript - 其他浏览器窗口在 Meteor.logout() 之后不会返回用户登录页面

haskell - 使用 netwire 的周期性与 at 电线

javascript - 使用带有大量参数的纯函数是否会降低性能?

从 rcpp 返回 R 函数

algorithm - 我如何在 haskell 中实现归纳图?

javascript - 如果它的子 TD 带有 JQuery 选择器,我如何选择一个 TR 而不是一个?

javascript - 无法正确验证javascript中的用户输入

javascript - C3.js - 在条形图中添加 X 轴和图例之间的间距

javascript - AJAX 调用在服务器端执行的顺序与客户端调用的顺序不同

f# - 在 F# 树上并行化函数的选项