卷曲一个无限参数的函数 [英] Currying a function that takes infinite arguments

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

问题描述

使用ES5,你如何克服一个需要无限参数的函数。
$ b

  function add (a,b,c){
返回a + b + c;





上面的函数只有三个参数,但我们希望我们的curried版本能够因此,所有以下测试用例都应该通过:

  var test = add(1); 

test(2); //应该返回3
test(2,3); //应该返回6
test(4,5,6); //应该返回16

以下是我提出的解决方案:

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

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

归还金额;


但是,我被告知它不是很 ;功能”的风格。

解决方案

部分原因是您的 add 函数不是非常功能性是因为它试图做的不仅仅是加上传递给它的数字。对于其他开发人员来看看你的代码会很困惑,看到一个 add 函数,当他们调用它时,得到一个返回给它们的函数而不是和。

  //使用你的add函数,我是期待6 
add(1,2,3)//返回另一个函数=混淆!






功能方法



功能方法是创建一个函数,允许您对任何其他函数进行压缩,并且简化您的添加函数

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

现在,如果你想咖喱这个函数,你只需要:

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

//您可以使用任意数量的参数来做到这一点
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)//返回6,真棒! 



继续使用功能方法



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



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

坚持数学主题,可以说我们有一个乘法函数,乘以传递给它的所有数字:

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

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


乘以(2,4,8)//返回64

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

对任何功能的方法,而不仅仅是数学方法。虽然提供的 curry 函数不支持所有的边界情况,但它为您的问题提供了一个功能强大的简单解决方案,可以轻松构建。


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.

解决方案

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.

For example:

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


The functional approach

The functional approach would be to create a function that allows you to curry any other functions, and simplify your add function:

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

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

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天全站免登陆