如何在未知数量的参数上计算函数

Ala*_*anH 6 javascript currying

说我有一个叫做的函数 multiplyDivide

如果我打电话multiplyDivide(2)(3)(4)(6),那就相当于2 * 3 / 4 * 6.

更新: 如果我事先不知道将要采用多少参数,是否可以编写这样的函数?例如,我可以multiplyDivide(1)(2)multiplyDivide(1)(2)(3)(4)...(n-1)(n)

sle*_*man 12

这有点可能,但您需要定义终止条件,因为问题与编写递归函数的问题基本相同.该函数需要一种方法来告诉天气它应该返回一个函数或一个值.

您如何表达对价值的需求取决于您.一种方法是检查参数是否通过:

// Using add instead of multiplyDivide to simplify example:

function add (num) {
    function adder (n) {
        if (n !== undefined) {
            num += n;
            return adder;
        }
        else { // terminate
            return num;
        }
    }
    return adder;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

var sum = add(1)(2)(3)(4)();
Run Code Online (Sandbox Code Playgroud)

否则它会返回一个你可以继续调用的函数:

var x = add(1)(2)(3)(4);
x = x(5)(6)(7);
x = x(8)(9)(10);

var sum = x();
Run Code Online (Sandbox Code Playgroud)

由于在js函数中是对象,因此您还可以将值getter实现为静态方法.它不是纯粹的功能,但使"API"更明确,更容易阅读:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.value = function(){
        return num
    };
    return adder;
}
Run Code Online (Sandbox Code Playgroud)

这将允许你做:

var sum = add(1)(2)(3)(4).value();
Run Code Online (Sandbox Code Playgroud)

您甚至可以通过覆盖内置.valueOf().toString()方法来获得幻想:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.valueOf = function(){
        return num
    };
    adder.toString = function(){
        return '' + num
    };
    return adder;
}
Run Code Online (Sandbox Code Playgroud)

这将允许你做:

var sum = add(1)(2)(3)(4) + 5; // results in 15
var txt = add(1)(2)(3)(4) + "hello"; // results in "10hello"
Run Code Online (Sandbox Code Playgroud)

这里的关键是你需要一种方法来告诉函数停止返回函数.

  • 我认为这应该是公认的答案。它实际上回答了这个问题。接受的答案甚至不使用柯里化。我有同样的问题,这篇文章给了我正在寻找的答案。谢谢! (3认同)

Kev*_*Bot 3

使用函数方法,您可以创建一个函数来“柯里化”另一个函数的参数。您将需要一种方法来告诉函数返回值,因此在这种情况下,调用函数而不传递任何参数将返回结果:

function curry(fn, ...values) {
    return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}
Run Code Online (Sandbox Code Playgroud)

该函数最酷的一点是您可以传递多个参数和/或继续调用该函数(1)(2, 3, 4)(5)

这里有几个例子:

function curry(fn, ...values) {
    return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}
Run Code Online (Sandbox Code Playgroud)

当然,这个示例确实暗示只是简单地重载该multiplyDivide函数并在准备好时将您的值传递给该函数:

function curry(fn, ...values) {
  return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}

function multiplyDivide(...args) {
  return args.reduce((total, next, i) => (i % 2) ? (total / next) : (total * next), args.shift());
}

let x = curry(multiplyDivide)(2)(3, 4)(6)();
console.log(x);

let y = curry(multiplyDivide)(5, 4, 2)(3);
y = y(3, 5)(1)();
console.log(y);
Run Code Online (Sandbox Code Playgroud)