柯里化一个接受无限参数的函数 [英] Currying a function that takes infinite arguments

查看:25
本文介绍了柯里化一个接受无限参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 ES5,你如何对一个带有无限参数的函数进行柯里化.

Using ES5, how do you curry a function that takes infinite arguments.

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

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

The function above takes only three arguments but we want our curried version to be able to take infinite arguments.

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

Hence, of all the following test cases should pass:

var test = add(1);

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

这是我想出的解决方案:

Here is the solution that I came up with:

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;
    }
}

但是,有人告诉我它不是很实用";风格.

However, I have been told that it's not very “functional” in style.

推荐答案

你的 add 函数不是很实用"的部分原因是它试图做的不仅仅是把数字加起来传递给它.如果其他开发人员查看您的代码,看到一个 add 函数,并且当他们调用它时,会得到一个返回给他们的函数而不是总和,这会让其他开发人员感到困惑.

Part of the reason your add function is not very "functional" is because it is attempting to do more than just add up numbers passed to it. It would be confusing for other developers to look at your code, see an add function, and when they call it, get a function returned to them instead of the sum.

例如:

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

<小时>

函数式方法

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

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;
    });
}

现在,如果你想咖喱这个函数,你可以这样做:

Now, if you want to curry this function, you would just do:

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,我可以这样做:

If I still want to add 1, 2, 3 up I can just do:

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

继续函数式方法

此代码现在可以在任何地方重复使用.

Continuing the functional approach

This code is now becoming reusable from everywhere.

您可以使用该柯里函数引用其他柯里函数,而无需任何额外的麻烦.

You can use that curry function to make other curried function references without any additional hassle.

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

Sticking with the math theme, lets say we had a multiply function that multiplied all numbers passed to it:

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

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

This functional currying approach allows you take that approach to any function, not just mathematical ones. Although the supplied curry function does not support all edge cases, it offers a functional, simple solution to your problem that can easily be built upon.

这篇关于柯里化一个接受无限参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆