41

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

sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10 
etc.

听说做不到 不过听说如果加+在前面sum就可以了。喜欢+sum(1)(2)(3)(4)
关于如何做到这一点的任何想法?

4

17 回答 17

78

不知道我是否明白你想要什么,但是

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

提琴手

于 2011-04-29T13:57:11.653 回答
32

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

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

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)(0)());

于 2016-02-28T21:09:59.467 回答
11

我将此修订作为自己的帖子发布,因为我显然还没有足够的声誉将其作为评论留下。这是@Rafael 出色解决方案的修订版。

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

console.log( +sum(1)(2)(3)(4) ); //10

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

于 2016-05-30T01:18:38.727 回答
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))

于 2017-10-18T17:17:30.270 回答
6

新的 ES6 方式,简洁明了。

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

const sum= x => y => (y !== undefined) ? sum(x + y) : x;

像这样称呼它-

sum(10)(30)(45)();
于 2020-03-04T06:07:11.067 回答
5

另一种略短的方法:

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

console.log(
  sum(1)(2)(),
  sum(3)(4)(5)()
);

于 2018-05-21T11:37:51.067 回答
4

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

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

这是另一个不需要的(),使用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());

const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
于 2019-02-20T15:12:04.630 回答
3

试试这个

function sum (...args) {
  return Object.assign(
    sum.bind(null, ...args),
    { valueOf: () => args.reduce((a, c) => a + c, 0) }
  )
}

console.log(+sum(1)(2)(3,2,1)(16))

在这里你可以看到一篇关于带有无限参数的携带函数的中等帖子

https://medium.com/@seenarowhani95/infinite-currying-in-javascript-38400827e581

于 2020-08-20T09:01:40.373 回答
2

这是一个更通用的解决方案,也适用于非一元参数:

const sum = function (...args) {
  let total = args.reduce((acc, arg) => acc+arg, 0)
  function add (...args2) {
    if (args2.length) {
      total = args2.reduce((acc, arg) => acc+arg, total)
      return add
    }
    return total
  }

  return add
}

document.write( sum(1)(2)() , '<br/>') // with unary params
document.write( sum(1,2)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)() , '<br/>') // with unary params
document.write( sum(1)(2,3)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)(4)() , '<br/>') // with unary params
document.write( sum(1)(2,3,4)() , '<br/>') // with ternary params

于 2020-01-13T15:38:18.613 回答
1
function add(a) {
    let curry = (b) => {
        a += b
        return curry;
    }
    curry[Symbol.toPrimitive] = (hint) => {
        return a;
    }
    return curry
}

console.log(+add(1)(2)(3)(4)(5));        // 15
console.log(+add(6)(6)(6));              // 18
console.log(+add(7)(0));                 // 7
console.log(+add(0));                    // 0
于 2020-09-13T10:54:49.450 回答
0

您可以使用以下功能

function add(num){
   add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
   add.sum += num; // increment it
   return add.toString = add.valueOf = function(){ 
      var rtn = add.sum; // we save the value
      return add.sum = 0, rtn // return it before we reset add.sum to 0
   }, add; // return the function
}

由于函数是对象,我们可以向它添加属性,当它被访问时我们正在重置。

于 2015-02-12T10:03:30.360 回答
0

这是使用迭代过程的另一种功能方式

const sum = (num, acc = 0) => {
    if !(typeof num === 'number') return acc;
    return x => sum(x, acc + num)
}

sum(1)(2)(3)()

和一条线

const sum = (num, acc = 0) => !(typeof num === 'number') ? acc : x => sum(x, acc + num)

sum(1)(2)(3)()
于 2018-08-08T10:43:53.983 回答
0

可能是一个老问题,但有点扩展的答案

function sum() {

    var args = [];
    args.push(...arguments);

    function sumOfAllArguments() {
        return args.reduce((prev,items)=>prev + items, 0)
    }

    function v() {
        arguments && args.push(...arguments);
        return arguments.length === 0 ? sumOfAllArguments() : v;
    }

    v.valueOf = v.toString = sumOfAllArguments;

    return v;

}
        
    

        console.log(sum(2)(2)(2)()) // 6
        console.log(sum(2)(2)(2).toString()) // 6
        console.log(sum(2)(2)(2).valueOf()) // 6
        console.log(+sum(2)(2)(2)) //6
        console.log(sum(2)(2)(2)) // f 6

        console.log(sum(2,2,2)(2,2)(2)) // f 12
        console.log(sum(2)(2,2)(2)()) //  8

于 2019-06-09T19:31:59.170 回答
-1

要使sum(1)as 可调用sum(1)(2),它必须返回一个函数。

可以调用该函数或将其转换为带有 的数字valueOf

function sum(a) {

   var sum = a;
   function f(b) {
       sum += b;
       return f;
    }
   f.toString = function() { return sum }
   return f
}
于 2015-07-29T10:15:37.900 回答
-1
   function sum(a){
    let res = 0;
    function getarrSum(arr){
            return arr.reduce( (e, sum=0) =>  { sum += e ; return sum ;} )
     }

    function calculateSumPerArgument(arguments){
            let res = 0;
            if(arguments.length >0){

            for ( let i = 0 ; i < arguments.length ; i++){
                if(Array.isArray(arguments[i])){
                    res += getarrSum( arguments[i]);
                }
                else{
                  res += arguments[i];
                }
             }
          }
            return res;
     }
    res += calculateSumPerArgument(arguments);



    return function f(b){
        if(b == undefined){
            return res;
        }
        else{
            res += calculateSumPerArgument(arguments);
            return f;
        }
    }

}
于 2018-03-30T10:47:48.773 回答
-1
let add = (a) => {
  let sum = a;
  funct = function(b) {
    sum += b;
    return funct;
  };

  Object.defineProperty(funct, 'valueOf', {
    value: function() {
      return sum;
    }
  });
  return funct;
};


console.log(+add(1)(2)(3))
于 2018-05-22T05:47:10.160 回答
-1

在查看了这里的其他一些解决方案之后,我想提供我的两个解决方案来解决这个问题。

使用 ES6 对两个项目进行柯里化:

const sum = x => y => (y !== undefined ) ? +x + +y : +x
sum(2)(2) // 4

这里我们指定了两个参数,如果第二个不存在我们只返回第一个参数。

对于三个或更多项目,它变得有点棘手;这是我的解决方案。对于任何其他参数,您可以将它们作为第三个添加

const sum = x => (y=0) => (...z) => +x + +y + +z.reduce((prev,curr)=>prev+curr,0)
sum(2)()()//2
sum(2)(2)()//4
sum(2)(2)(2)//6
sum(2)(2)(2,2)//8

我希望这对某人有所帮助

于 2021-03-05T16:22:18.927 回答