Create a function with an undefined number of consecutive calls

As part of the programming task, we are tasked with creating a function with an indefinite number of consecutive calls. As an example, suppose a function returns just the sum of the arguments provided, 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 using the allowed empty function call at the end as an indication of the end of the calls.

I 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 traversal of the function object, which is not ideal. My question here is whether there is a way to solve the problem in a purely recursive way.

As a remark, I do not believe that the problem can be solved if this last empty call () is not specified, but if I am wrong, let me know.

Update

This question was answered in CodeReview: https://codereview.stackexchange.com/a/153999/129579

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

+6
source share
2 answers

You can use closures to achieve what you want:

 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 _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 the following order:

  • sum with parameter 1 , which initializes result to 0 and will call
  • _sum with the same parameter 1 , which will add it to result and return a new _sum parameter, which will be called like this:
  • _sum is called with parameter 7 , adds it and returns a new _sum , so the new
  • _sum is called with parameter 3 , ... spawns another
  • _sum , which will not have any parameter, so if(typeof a != "undefined") will fail, and _sum will return result instead.

The actual sum is called only once at the beginning to complete the initialization. These are, as I said, _sum , which interlock after this to the end.

+3
source

Basically, you can use the external function sum for the initial call and the closure on the starting value of a and the internal function fn , which is repeated and will only exit if arguments.length is zero.

If b is specified, the variable a updated and the internal function fn returned.

 function sum(a) { return function fn(b) { if (!arguments.length) { return a; } a += b; return fn; }; } console.log(sum(1)()); console.log(sum(1)(2)()); console.log(sum(1)(2)(3)()); 

Edit to call the sum without argument

 function sum(a) { return arguments.length ? function fn(b) { if (!arguments.length) { return a; } a += b; return fn; } : 0; } console.log(sum()); console.log(sum(1)()); console.log(sum(1)(2)()); console.log(sum(1)(2)(3)()); 
0
source

Source: https://habr.com/ru/post/1014550/


All Articles