Variadic curried sum函数

Yar*_*lev 27 javascript currying

我需要一个js sum函数来像这样工作:

sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10 
etc.
Run Code Online (Sandbox Code Playgroud)

我听说不能这样做.但是听说如果加+在前面sum就可以做到.喜欢+sum(1)(2)(3)(4).
有关如何做到这一点的任何想法?

Raf*_*ael 65

不确定我是否理解你想要的东西,但是

function sum(n) {
  var v = function(x) {
    return sum(n + x);
  };

  v.valueOf = v.toString = function() {
    return n;
  };

  return v;
}

console.log(+sum(1)(2)(3)(4));
Run Code Online (Sandbox Code Playgroud)

的jsfiddle

  • +将sum()的结果转换为数字.在这种情况下,JavaScript调用对象的.valueOf方法.由于我正在返回匿名函数,这有助于将其转换为原始类型.正如您所看到的,我用自己的覆盖了原生的.valueOf. (7认同)
  • @Yaroslav:如果将结果转换为字符串(例如,使用alert()时),它将起作用.使用本机console.log时,您将看到function(){return n + x; 在控制台中. (5认同)
  • @maverick 不,`valueOf` 由 JavaScript 内部调用,例如在运行一元 `+` 运算符时。根据 ES5 规范,“+”运行抽象“ToNumber”,后者又调用抽象“ToPrimitive”,后者调用内部方法“[[DefaultValue]]”,最终调用“valueOf”。您可以从[此处](https://es5.github.io/#x11.4.6)开始跟踪调用链 (2认同)

小智 18

这是在最后一次调用中使用空括号作为关键键的示例(来自我上次的采访):

总和(1)(4)(66)(35)(3)()

function sum(numberOne) {
  var count = numberOne;
  return function by(numberTwo) {
    if (numberTwo === undefined) {
      return count;
    } else {
      count += numberTwo;
      return by;
    }
  }
}
console.log(sum(1)(4)(66)(35)(3)());
Run Code Online (Sandbox Code Playgroud)


小智 10

新的 ES6 方式并且简洁。

当你想终止调用并获取最终值时,你必须在最后传递empty()。

const sum= x => y => (y !== undefined) ? sum(x + y) : x;
Run Code Online (Sandbox Code Playgroud)

像这样称呼它 -

sum(10)(30)(45)();
Run Code Online (Sandbox Code Playgroud)


Bra*_*rad 7

我发布这个版本作为自己的帖子,因为我显然没有足够的声誉,只是留下它作为评论.这是对@Rafael优秀解决方案的修订.

function sum (n) {
    var v = x => sum (n + x);
    v.valueOf = () => n; 
    return v;
}

console.log(+sum(1)(2)(3)(4)); //10
Run Code Online (Sandbox Code Playgroud)

我没有看到保留v.toString位的原因,因为它似乎没有必要.如果我错误地这样做,请在评论中告诉我为什么需要v.toString(它没有通过我的测试就好了).将其余的匿名函数转换为箭头函数以便于阅读.

  • `console.log("The result is " + sum(1) + "!")` 返回字符串 `​The result is 1!`,即使在 `v.valueOf` 语句中省略了 `toString` `sum` 函数,正如我上面所做的那样。仍然不清楚添加“toString”会实现什么,但尚未发生。 (2认同)

Art*_*kun 6

这是一个使用 ES6 和 的解决方案toString,类似于@Vemba

function add(a) {
  let curry = (b) => {
    a += b
    return curry
  }
  curry.toString = () => a
  return curry
}

console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))
Run Code Online (Sandbox Code Playgroud)


Jon*_*lms 6

另一种稍微短一点的方法:

const sum = a => b => b? sum(a + b) : a;

console.log(
  sum(1)(2)(),
  sum(3)(4)(5)()
);
Run Code Online (Sandbox Code Playgroud)


use*_*533 5

这是 ES6 Javascript 中使用通用可变参数柯里函数的解决方案,但需要注意的是需要使用final()来调用参数:

const curry = (f) =>
   (...args) => args.length? curry(f.bind(0, ...args)): f();
Run Code Online (Sandbox Code Playgroud)
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true
Run Code Online (Sandbox Code Playgroud)

这是另一个不需要的(),使用valueOf@rafael的答案。我觉得valueOf以这种方式使用(或者也许根本)对于阅读您的代码的人来说非常令人困惑,但每个人都有自己的方式。

该答案中的内容toString是不必要的。在内部,当 javascript 执行类型强制时,它总是valueOf()在调用toString().


// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );

const curry = autoInvoke((f) =>
   (...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());

Run Code Online (Sandbox Code Playgroud)
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
Run Code Online (Sandbox Code Playgroud)