Variadic curried sum function

China☆狼群 提交于 2019-11-26 03:14:42

问题


I need a js sum function to work like this:

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

I heard it can\'t be done. But heard that if adding + in front of sum can be done. Like +sum(1)(2)(3)(4).
Any ideas of how to do this?


回答1:


Not sure if I understood what you want, but

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

JsFiddle




回答2:


This is an example of using empty brackets in the last call as a close key (from my last interview):

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



回答3:


I'm posting this revision as its own post since I apparently don't have enough reputation yet to just leave it as a comment. This is a revision of @Rafael 's excellent solution.

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

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

I didn't see a reason to keep the v.toString bit, as it didn't seem necessary. If I erred in doing so, please let me know in the comments why v.toString is required (it passed my tests fine without it). Converted the rest of the anonymous functions to arrow functions for ease of reading.




回答4:


Here is a solution that uses ES6 and toString, similar to @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))



回答5:


Here's a solution with a generic variadic curry function in ES6 Javascript, with the caveat that a final () is needed to invoke the arguments:

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

Here's another one that doesn't need (), using valueOf as in @rafael's answer. I feel like using valueOf in this way (or perhaps at all) is very confusing to people reading your code, but each to their own.

The toString in that answer is unnecessary. Internally, when javascript performs a type coersion it always calls valueOf() before calling 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



回答6:


You can make use of the below function

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
}

Since functions are objects, we can add properties to it, which we are resetting when it's been accessed.




回答7:


Another slightly shorter approach:

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

Usable as:

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



回答8:


To make sum(1) callable as sum(1)(2), it must return a function.

The function can be either called or converted to a number with valueOf.

function sum(a) {

   var sum = a;
   function f(b) {
       sum += b;
       return f;
    }
   f.toString = function() { return sum }
   return f
}



回答9:


Might be an old question but a little extended answer

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



回答10:


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

}



回答11:


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



回答12:


Here is another functional way using an iterative process

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

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

and one-line

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

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


来源:https://stackoverflow.com/questions/5832891/variadic-curried-sum-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!