52

I want to make this syntax possible:

var a = add(2)(3); //5

based on what I read at http://dmitry.baranovskiy.com/post/31797647

I've got no clue how to make it possible.

TylerH
  • 20,799
  • 66
  • 75
  • 101
rajakvk
  • 9,775
  • 17
  • 46
  • 49

33 Answers33

108

You need add to be a function that takes an argument and returns a function that takes an argument that adds the argument to add and itself.

var add = function(x) {
    return function(y) { return x + y; };
}
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 26
    The ES2015 arrow syntax facilitates the job: `const add = x => y => x + y;` –  Jun 24 '16 at 21:38
  • @tvanfosson I'm new in JS. And I have a doubt. Why it(`var add = function()` should not be `function add(){ }`? `function add()` also give the same result. – mkHun Apr 14 '17 at 12:24
  • 1
    @mkHun the syntax I've shown defines an anonymous function and assigns it to the variable named `add`. The second defines a named function with the name `add`. They both work. – tvanfosson Apr 14 '17 at 13:25
  • @tvanfosson I think my below solution is more exciting with unlimited adding chain – hien Jul 17 '18 at 08:59
  • Could you please tell me, do we have any specific name for this kind of syntax, I have got the same kind of question from my interviewer last night – Gopala Raja Naika Apr 02 '20 at 12:10
40
function add(x) {
    return function(y) {
        return x + y;
    };
}

Ah, the beauty of JavaScript

This syntax is pretty neat as well

function add(x) {
    return function(y) {
        if (typeof y !== 'undefined') {
            x = x + y;
            return arguments.callee;
        } else {
            return x;
        }
    };
}
add(1)(2)(3)(); //6
add(1)(1)(1)(1)(1)(1)(); //6
Oscar Kilhed
  • 1,796
  • 1
  • 13
  • 16
18

It's about JS curring and a little strict with valueOf:

function add(n){
  var addNext = function(x) {
    return add(n + x);
  };

  addNext.valueOf = function() {
    return n;
  };

  return addNext;
}

console.log(add(1)(2)(3)==6);//true
console.log(add(1)(2)(3)(4)==10);//true

It works like a charm with an unlimited adding chain!!

hien
  • 1,988
  • 2
  • 17
  • 13
  • const add = (a) => { let f = (b) => add(a + b) f.valueOf = () => a return f } – Aymon Fournier Aug 21 '18 at 21:42
  • 2
    What in the bloody heck is going on when assigning values?! Your same example behaves differentlly with this escenarios: a) console.log(' should equal 6 => ', add(1)(2)(3)); b) console.log('should NOT matter', add(1)(2)(3) === 6); Can you please explain what's going under the hood (besides rotenJS which is obviouse ;) ) – aemonge Feb 25 '19 at 16:03
  • Because func `valueOf` of `add` will return a string – hien Feb 26 '19 at 07:25
  • 1
    It's only working for number comparison. How to get value instead of function body after last `add` call, anyone? – vbarinov Mar 21 '19 at 16:19
  • 1
    I know that writing "thanks" in comments is a big no-no. But just this once, thanks. Really. – RaidenF Jun 16 '19 at 20:45
  • It even works for `add(1)`. It would be great, if you gave an expanded explanation. – madfcat Jan 29 '23 at 04:16
15
function add(x){
  return function(y){
    return x+y
  }
}

First-class functions and closures do the job.

NVI
  • 14,907
  • 16
  • 65
  • 104
14
function add(n) {
  sum = n;
  const proxy = new Proxy(function a () {}, {
    get (obj, key) {
      return () => sum;
    },
    apply (receiver, ...args) {
      sum += args[1][0];
      return proxy;
    },
  });
  return proxy
}

Works for everything and doesn't need the final () at the end of the function like some other solutions.

console.log(add(1)(2)(3)(10));    // 16
console.log(add(10)(10));         // 20
Ben Hernandez
  • 857
  • 1
  • 11
  • 23
  • 1
    Wow can you explain this, I have no idea what's going on. – Aymon Fournier Mar 08 '18 at 04:38
  • So I mostly referenced http://2ality.com/2014/12/es6-proxies.html when I was learning about Proxies but the short version of this is that in javascript you can create traps for pretty much every operation. Luckily the operations for applying a function are different than the one where the value is determined. So I trapped both the apply and the getter of a function to create this. You probably already do this in your es6 classes with getters and setters (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) this is just a bit more explicit – Ben Hernandez Mar 11 '18 at 06:41
  • @GaleelBhasha not sure why jsFiddle isn't working but it works in repl.it (https://repl.it/repls/DirectPolitePasswords) and in my local node repl. – Ben Hernandez Apr 30 '18 at 18:29
  • 1
    Proxy is oke, but I think my below answer is easier and readable! – hien Jul 13 '18 at 03:23
  • 1
    @hien I didn't even consider that, that is a really cool solution. – Ben Hernandez Jul 15 '18 at 00:53
  • It's a cool sulotion! – Ha0ran Mar 22 '22 at 08:26
13

try this will help you in two ways add(2)(3) and add(2,3)

1.)

 function add(a){ return function (b){return a+b;} }

    add(2)(3) // 5

2.)

function add(a,b){
        var ddd = function (b){return a+b;};
        if(typeof b =='undefined'){
            return ddd;
        }else{
            return ddd(b);
        }
    }

add(2)(3) // 5
add(2,3) // 5
vasudev
  • 410
  • 5
  • 13
11

ES6 syntax makes this nice and simple:

const add = (a, b) => a + b;

console.log(add(2, 5)); 
// output: 7

const add2 = a => b => a + b;

console.log(add2(2)(5));
// output: 7
satyrsynth
  • 399
  • 1
  • 4
  • 14
  • how do you make it work with one argument as well as currying, e.g. add(1) === 1, and add(1)(2) === 3 – Aymon Fournier Mar 08 '18 at 03:44
  • 1
    @AymonFournier I'm not 100% sure, but I think it is not possible for add(1) to return both a Function and a Number value at the same time. At the time of calling add(1), you cannot be sure whether there is going to be another call with `2` as argument, or whether this is the final call. – florish Aug 21 '18 at 08:18
  • 2
    @AymonFournier Oh, I stand corrected, a trick is to use [valueOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf). See someone else's answer for more details: https://stackoverflow.com/a/51317189/964545 – florish Aug 21 '18 at 08:19
6

Arrow functions undoubtedly make it pretty simple to get the required result:

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

console.log(Sum(3)(4)(2)(5)()); //14

console.log(Sum(3)(4)(1)()); //8
Amir Danish
  • 418
  • 5
  • 8
  • when you go this far its amazing. and also its easy to forget that 3+4+2+5 is not 19 :) – pera Jan 31 '20 at 14:44
4

This is a generalized solution which will solve add(2,3)(), add(2)(3)() or any combination like add(2,1,3)(1)(1)(2,3)(4)(4,1,1)(). Please note that few security checks are not done and it can be optimized further.

function add() {
 var total = 0;

 function sum(){
  if( arguments.length ){
   var arr = Array.prototype.slice.call(arguments).sort();
   total = total + arrayAdder(arr);
   return sum;
  }
  else{
   return total;
  }
 }

 if(arguments.length) {
  var arr1 = Array.prototype.slice.call(arguments).sort();
  var mytotal = arrayAdder(arr1);
  return sum(mytotal);
 }else{
  return sum();
 }

 function arrayAdder(arr){
  var x = 0;
  for (var i = 0; i < arr.length; i++) {
   x = x + arr[i];
  };
  return x;
 }
}
add(2,3)(1)(1)(1,2,3)();
Debajit Majumder
  • 824
  • 1
  • 11
  • 22
4

This will handle both

add(2,3) // 5

or

add(2)(3) // 5

This is an ES6 curry example...

const add = (a, b) => (b || b === 0) ? a + b : (b) => a + b;
4

This is concept of currying in JS.
Solution for your question is:

function add(a) {
  return function(b) {
    return a + b;
  };
}

This can be also achieved using arrow function:

let add = a => b => a + b;

solution for add(1)(2)(5)(4)........(n)(); Using Recursion

function add(a) {
  return function(b){
    return b ? add(a + b) : a;
  }
}

Using ES6 Arrow function Syntax:

let add = a => b => b ? add(a + b) : a;
3

in addition to what's already said, here's a solution with generic currying (based on http://github.com/sstephenson/prototype/blob/master/src/lang/function.js#L180)

Function.prototype.curry = function() {
    if (!arguments.length) return this;
    var __method = this, args = [].slice.call(arguments, 0);
    return function() {
      return __method.apply(this, [].concat(
        [].slice.call(args, 0),
        [].slice.call(arguments, 0)));
   }
}


add = function(x) {
    return (function (x, y) { return x + y }).curry(x)
}

console.log(add(2)(3))
user187291
  • 53,363
  • 19
  • 95
  • 127
2

Concept of CLOSURES can be used in this case.
The function "add" returns another function. The function being returned can access the variable in the parent scope (in this case variable a).

function add(a){

    return function(b){
        console.log(a + b);
    }

}


add(2)(3);

Here is a link to understand closures http://www.w3schools.com/js/js_function_closures.asp

Rahul Arora
  • 4,503
  • 1
  • 16
  • 24
2

With ES6 spread ... operator and .reduce function. With that variant you will get chaining syntax but last call () is required here because function is always returned:

function add(...args) {
    if (!args.length) return 0;
    const result = args.reduce((accumulator, value) => accumulator + value, 0);
    const sum = (...innerArgs) => {
        if (innerArgs.length === 0) return result;
        return add(...args, ...innerArgs);    
    };
    return sum;
}




// it's just for fiddle output
document.getElementById('output').innerHTML = `
<br><br>add() === 0: ${add() === 0 ? 'true' : 'false, res=' + add()}
<br><br>add(1)(2)() === 3: ${add(1)(2)() === 3 ? 'true' : 'false, res=' + add(1)(2)()}
<br><br>add(1,2)() === 3: ${add(1,2)() === 3 ? 'true' : 'false, res=' + add(1,2)()}
<br><br>add(1)(1,1)() === 3: ${add(1)(1,1)() === 3 ? 'true' : 'false, res=' + add(1)(1,1)()}
<br><br>add(2,3)(1)(1)(1,2,3)() === 13: ${add(2,3)(1)(1)(1,2,3)() === 13 ? 'true' : 'false, res=' + add(2,3)(1)(1)(1,2,3)()}
`;
<div id='output'></div>
Maksim Nesterenko
  • 5,661
  • 11
  • 57
  • 91
2
const add = a => b => b ? add(a+b) : a;

console.log(add(1)(2)(3)());

Or (`${a} ${b}`) for strings.

LBoyle
  • 21
  • 3
2

can try this also:

let sum = a => b => b ? sum(a + b) :a
console.log(sum(10)(20)(1)(32)())   //63
showdev
  • 28,454
  • 37
  • 55
  • 73
2
const sum  = function (...a) {
    const getSum = d => {
        return d.reduce((i,j)=> i+j, 0);
    };

    a = getSum(a);
    return function (...b) {
        if (b.length) {
            return sum(a + getSum(b)); 
        }
        return a;
    }
};
console.log(sum(1)(2)(3)(4,5)(6)(8)())
1
function add(a, b){
 return a && b ? a+b : function(c){return a+c;}
}

console.log(add(2, 3));
console.log(add(2)(3));
1

This question has motivated so many answers already that my "two pennies worth" will surely not spoil things.

I was amazed by the multitude of approaches and variations that I tried to put "my favourite" features, i. e. the ones that I would like to find in such a currying function together, using some ES6 notation:

const add=(...n)=>{
 const vsum=(a,c)=>a+c;
 n=n.reduce(vsum,0);
 const fn=(...x)=>add(n+x.reduce(vsum,0));
 fn.toString=()=>n; 
 return fn;
}

let w=add(2,1); // = 3
console.log(w()) // 3
console.log(w); // 3
console.log(w(6)(2,3)(4)); // 18
console.log(w(5,3)); // 11
console.log(add(2)-1); // 1
console.log(add()); // 0
console.log(add(5,7,9)(w)); // 24
.as-console-wrapper {max-height:100% !important; top:0%}

Basically, nothing in this recursively programmed function is new. But it does work with all possible combinations of arguments mentioned in any of the answers above and won't need an "empty arguments list" at the end.

You can use as many arguments in as many currying levels you want and the result will be another function that can be reused for the same purpose. I used a little "trick" to also get a numeric value "at the same time": I redefined the .toString() function of the inner function fn! This method will be called by Javascript whenever the function is used without an arguments list and "some value is expected". Technically it is a "hack" as it will not return a string but a number, but it will work in a way that is in most cases the "desired" way. Give it a spin!

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
1

Simple Recursion Solution for following use cases

add(); // 0

add(1)(2)(); //3

add(1)(2)(3)(); //6
function add(v1, sum = 0) {
  if (!v1) return sum;
  sum += v1
  return (v2) => add(v2, sum);
}
Audwin Oyong
  • 2,247
  • 3
  • 15
  • 32
Pavneet Kaur
  • 729
  • 7
  • 5
0

function add() { var sum = 0;

    function add() {
        for (var i=0; i<arguments.length; i++) {
            sum += Number(arguments[i]);
        }
        return add;
    }
    add.valueOf = function valueOf(){
        return parseInt(sum);
    };
    return add.apply(null,arguments);
}

// ...

console.log(add() + 0);               // 0
console.log(add(1) + 0);/*                 // 1
console.log(add(1,2) + 0);               // 3
Vishesh Mishra
  • 988
  • 9
  • 12
0
function A(a){
  return function B(b){
      return a+b;
  }
}

I found a nice explanation for this type of method. It is known as Syntax of Closures

please refer this link Syntax of Closures

Nithin Mohan
  • 750
  • 16
  • 34
0

Simply we can write a function like this

    function sum(x){
      return function(y){
        return function(z){
          return x+y+z;
        }
      }
    }

    sum(2)(3)(4)//Output->9
0

Don't be complicated.

var add = (a)=>(b)=> b ? add(a+b) : a;
console.log(add(2)(3)()); // Output:5

it will work in the latest javascript (ES6), this is a recursion function.

kailash N
  • 1
  • 2
0

Here we use concept of closure where all the functions called inside main function iter refer and udpate x as they have closure over it. no matter how long the loop goes , till last function , have access to x.

function iter(x){    
return function innfunc(y){
//if y is not undefined
if(y){
//closure over ancestor's x
x = y+x;
return innfunc;
}
else{
//closure over ancestor's x
return x;
    }
  }
}

iter(2)(3)(4)() //9 iter(1)(3)(4)(5)() //13

Ayyappa Gollu
  • 906
  • 7
  • 16
0

let multi = (a)=>{
 return (b)=>{
  return (c)=>{
   return a*b*c
  }
 }
}
multi (2)(3)(4) //24

let multi = (a)=> (b)=> (c)=> a*b*c;
multi (2)(3)(4) //24
0

we can do this work using closure.

    function add(param1){
      return function add1(param2){
      return param2 = param1 + param2;
    }
  }
  console.log(add(2)(3));//5
Kunal Ranjan
  • 192
  • 1
  • 2
  • 13
0

I came up with nice solution with closure, inner function have access to parent function's parameter access and store in its lexical scope, when ever we execute it, will get answer

    const Sum = function (a) {
        return function (b) {
            return b ? Sum(a + b) : a;
        }
    };

    Sum(1)(2)(3)(4)(5)(6)(7)() // result is 28
    Sum(3)(4)(5)() // result is 12
    Sum(12)(10)(20) // result is 42

enter image description here

  • 1
    Hi and welcome to stackoverflow, and thank you for your answer. Rather than just posting a block of code, can you give a short explanation to what the issue is you solved and how you solved it? This will help people who find this question in the future to better understand the issue and how to deal with it. – Plutian Dec 06 '19 at 09:46
0

You should go in for currying to call the function in the above format.

Ideally, a function which adds two numbers will be like,

let sum = function(a, b) {
  return a + b;
}

The same function can be transformed as,

let sum = function(a) {
  return function(b) {
    return a+b;  
  }
}

console.log(sum(2)(3));

Let us understand how this works.

When you invoke sum(2), it returns

function(b) {
    return 2 + b;
}

when the returned function is further invoked with 3, b takes the value 3. The result 5 is returned.

More Detailed Explanation:

let sum = function(a) {
  return function(b) {
    return a + b;
  }
}

let func1 = sum(2);
console.log(func1);

let func2 = func1(3)
console.log(func2);

//the same result can be obtained in a single line

let func3 = sum(2)(3);
console.log(func3);

//try comparing the three functions and you will get more clarity.
0

This is a short solution:

const add = a => b => {
  if(!b) return a;
  return add(a + b);
}

add(1)(2)(3)() // 6
add(1)(2)(3)(4)(5)() // 15
webHasan
  • 461
  • 3
  • 11
0

// executor function
const sum = (a,b,c) => a+b+c;

// curried function
function curry(fn){
  return function curried(...args) {
    if(args.length >= fn.length){
      return fn.apply(this,args);
    } else {
      return function (...arg) {
        return curried(...arg, ...args)
      }
    }
  }
}

const curriedSum = curry(sum);
console.log(curriedSum(1,2,3));
console.log(curriedSum(1)(2)(3));
console.log(curriedSum(1)(2,3));
  • Welcome to SO! Please don't post code-only answers but add a little textual explanation about how and why your approach works and what makes it different from the other answers given. You can find out more at our ["How to write a good answer"](https://stackoverflow.com/help/how-to-answer) page. – ahuemmer Dec 28 '22 at 08:36
-1

function add () {
    var args = Array.prototype.slice.call(arguments);
 
    var fn = function () {
        var arg_fn = Array.prototype.slice.call(arguments);
        return add.apply(null, args.concat(arg_fn));
    }
 
    fn.valueOf = function () {
        return args.reduce(function(a, b) {
            return a + b;
        })
    }
 
    return fn;
}

console.log(add(1));
console.log(add(1)(2));
console.log(add(1)(2)(5));

from http://www.cnblogs.com/coco1s/p/6509141.html

Hsiao
  • 1
-1
    let add = (a, b) => b === undefined ? add.bind(null, a) : a + b;
    console.log(add(10, 5)); //15
    console.log(add(10)(5)); //15

/* In the arrow function which returns a ternary expression, we explicitly check if the 2nd argument(b) is passed in or not b==="undefined" in both cases of add(a,b) and add(a)(b).

  1. if "undefined" in the case of add(a)(b) it uses "add.bind(null,a)", the "bind" method is associated with all functions(functions are objects) which creates a new function that is returned by the arrow function and passes in:
    • "null" for the first argument "the context its binding to which allows it to default to the window object"
    • "a" the second argument to be returned with the new function.
    • so when the new function is called at this point add(a)>>>(b) "b" is no longer undefined so the ternary switches to a+b.
  2. If not b==="undefined" in the case of add(a, b) the ternary switches to a+b */
  • While this code may answer the question, providing additional context regarding *why* and/or *how* this code answers the question improves its long-term value. – Tân Dec 10 '19 at 05:29
  • thanks for the advice, does the addition of the edited comments suffice – Sheldon Small Apr 10 '20 at 20:56