Having a difficult time understanding Currying with infinite arguments

I understand the basic examples of currying using simple adder functions like:

function adder(a){
    return function(b){
        return a+b
    }
}
let adderFn = adder(1)
let getTwo = adderFn(1) 

However, I’m having a hard time understanding how to create a currying function like the one in this CodeWars kata: A Chain Adding Function

I’d really appreciate it if someone could break down the solution for me and explain what is going on step-by-step:

function add(n){
  var fn = function(x) {
    return add(n + x);
  };
  
  fn.valueOf = function() {
    return n;
  };
  
  return fn;
}

Also, any good resources to help with my understanding would be great. I’ve looked at almost every currying video I could find on Youtube and they all explain using the same adder function example and don’t really go any deeper and/or provide alternative examples.

Have a look at this:

valueOf returns the primitive value of a function.

The basic concept between currying for a fixed number of arguments and potentially unlimited arguments lies in knowing when you reach the end of the arguments list. The answer can be rewritten in a different way like this:

function add (num) {
    // you have to name the function when you have unlimited arguments
    //  because you have to have the same function to keep passing down
    //  the example you gave used 'fn' but it's a poor naming convention
    function adder(n) {
      // if the next potential argument is falsey, we can exist and return accumulated sum
      if (!n) {
        return num;
      } else {
        // otherwise we keep a running sum by adding the newest argument to num
        //  we chain the process by returning our named function
        num += n;
        return adder;
      }
    }
  
    return adder;
}

// our function returns a function, so you have to call it. 
//  your example code uses `valueOf` so it would end up being
//  add(1)(2)(3).valueOf(). I have seen an interviewer show me 
//  that he/she wanted it to be called with the extra open/close paren
console.log(add(1)(2)(3)());
2 Likes

The main tools to emulate currying in a language in which function application is done via parenthesis relies on:

  1. The ability to access the amount of expected arguments (parameters)
  2. The ability to access the argument list and its length
  3. Returning and receiving functions from functions (which is almost any popular language nowadays, even Java 8 has this capability).

In Javascript you have the ability to access the argument list of a function as:

// The modern ES6 way
function logArgs(...args) {
  console.log(args)
}

// The old way using the array-like object "arguments"
function logArgs() {
  console.log(arguments)
}

And the number of parameters a function has:

function add(x, y) { return x + y }

console.log(add.length) // 2

With this you can keep returning functions with less parameters than there is passed arguments for as long as you haven’t already exhausted all the expected parameters.

So there’s an if statement involved.