Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a function with an undetermined number of successive calls

As part of a programming challenge, we are tasked with creating a function with an undetermined number of successive calls. As an example, let's say the function returns simply the sum of the provided arguments, it should work as follows :

sum(4)() // 4
sum(4)(5)() // 9
sum(4)(5)(9)() // 18
sum(4)(5)(9)(1)() // 19
// etc...

The problem is simplified by the allowed empty function call at the end as an indication of end of calls.

I have worked on a solution that does the job but using global variables inside the function itself :

var sum = function (a) {
    if (!sum.init) {
        sum.total = 0;
        sum.init = true;
    }
    if (!arguments.length) {
        sum.init = false;
        return sum.total;
    }
    sum.total += a;
    return sum;
};

This solution works but uses state, global variables and function object trickery which is not ideal. My question here is whether there is a way to solve the problem in a purely recursive way.

As a side note, I do not believe the problem can be solved if that last empty call () is not provided, but if I'm wrong please let me know.

Update

This issue has been answered in CodeReview : https://codereview.stackexchange.com/a/153999/129579

A neet solution that does not rely on global scope and is purely functional.

like image 541
Ghassen Louhaichi Avatar asked Jan 30 '17 13:01

Ghassen Louhaichi


People also ask

How do you pass n number of arguments to a function?

Rest Parameters (ES6) The rest parameter provides an easier and cleaner way of working with an indefinite number of arguments. Let's rewrite the above example with a rest parameter. Using the rest parameter, which is the same syntax as the spread operator, we can pass an indefinite number of parameters to our function.

What is$( function in js?

$(...); Which is the "jQuery function." $ is a function, and $(...) is you calling that function. The first parameter you've supplied is the following: function() {} The parameter is a function that you specified, and the $ function will call the supplied method when the DOM finishes loading.

Can you nest functions JavaScript?

JavaScript allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to).

Can I define a function inside a function?

A function which is defined inside another function is known as inner function or nested functio n. Nested functions are able to access variables of the enclosing scope. Inner functions are used so that they can be protected from everything happening outside the function. This process is also known as Encapsulation .


1 Answers

You can make use of closures to acheive what you want like this:

function sum(value){
  // the closure variable that will be accessible for all the _sum calls (initialised to 0 for every sum call).
  var result = 0;
  
  // the function that will be returned (sum will only get called once to initialize the result to 0. It's _sum which will be returned as much as possible)
  function _sum(a){
    // if we passed a parameter, then add it to result and return a new _sum
    if(typeof a != "undefined"){
      result += a;
      return _sum;
    }
    // if we didn't return the result
    else
      return result;
  }
  // of course after initializing result we need to call _sum that handle the actual summing and return whatever it returns (if value is defined, it will return another `_sum` if not it will return the value of result which will be 0 at first) from now on sum will have nothing to do with the rest of the calls (()()()... )
  return _sum(value);
}

console.log("sum() = " + sum());
console.log("sum(7)() = " + sum(7)());
console.log("sum(5)(6)(7)() = " + sum(5)(6)(7)());

// will return 0 because we call sum again
console.log("sum() = " + sum());

NOTE: That sum(1)(7)(3)()); will call, in this order:

  1. sum with the parameter 1 which will initialize result to 0 and call
  2. _sum with the same parameter 1 which will add it to result and return a new inctance of _sum which will be called so the following
  3. _sum get called with the parameter 7, add it and return a new _sum so the new
  4. _sum get called with the parameter 3, ... spawn another
  5. _sum that will have no parameter, therefore if(typeof a != "undefined") will fail and this _sum will return result instead.

The actual sum is only called once at the begining to do the initialization. It's, as I said, _sum that get chained after that all the way to the end.

like image 163
ibrahim mahrir Avatar answered Oct 16 '22 18:10

ibrahim mahrir