Roman
Roman

Reputation: 363

(My failed) Javascript challenge: function add()()() with closures

Need to write a function, that can get up to 3 arguments and return a sum. Here is a ways, how it can be called:

add(2, 5, 10); // 17
add(2, 5)(10); // 17
add(2)(5)(10); // 17
add(2)(5, 10); // 17

I have write a function, that can do it:

function add(a) {
  var currentSum = [].reduce.call(arguments, function(c, d) { return c + d; });

  function f(b) {
    currentSum += [].reduce.call(arguments, function(c, d) { return c + d; });
    return f;
  }

  f.toString = function() {
    return currentSum;
  };

  return f;
}

BUT! The challenge task says that I CAN'T use toString of valueOf to get result. How can I solve it?

P.S. I have noticed that I failed the challenge, so why I'm asking.

Upvotes: 1

Views: 173

Answers (5)

Roli Agrawal
Roli Agrawal

Reputation: 2466

You can do something like this:

function ab(a,b,c){
   if(arguments.length==3){return(a+b+c)};
   if(arguments.length==2){return(function(c){return(a+b+c)})};
   if(arguments.length==1){
   return(function(b,c){ if(arguments.length==2) {return(a+b+c)}
   else{ return(function(c){console.log(a,b,c); return(a+b+c)})}
}
)} 
  } ab(1,67,9);

Upvotes: 0

AnujKumar
AnujKumar

Reputation: 1

Below fix would resolve this

Create "add" function as below which would handle up to 3 arguments

function add(a,b,c) {
  return (((a!=null && a>0)?a:0) + ((b!=null && b >0)?b:0 ) + ((c!=null && c >0)?c:0 ));
}

You just need to call it and pass arguments as per your requirement like

add(2);//will give 2 as result
add(2,3);//Will give 5 as result
add(2,3,4)//will give 9 as result

Although if you want to make format strict to pass 3 arguments then you can pass null in arguments i.e. add(2) and add(2,null,null) would provide same result. Hope this would solve your issue.

Upvotes: 0

georg
georg

Reputation: 215009

Compare the arity of the function (add.length) with the actual number of arguments and return a closure if there are less arguments:

Array.from = Array.from || function(x) { return [].slice.call(x) };

function add(a, b, c) {
  
  var args = Array.from(arguments);
  
  if(args.length < add.length)
    return function() {
        return add.apply(null,
                         args.concat(Array.from(arguments)));
    }

  return args.reduce(function(x, y) { return x + y }, 0);
}

document.write("<pre>")
document.writeln(add(1)(2)(3));
document.writeln(add(1, 2)(3));
document.writeln(add(1)(2, 3));
document.writeln(add(1, 2, 3));

Upvotes: 1

a_pradhan
a_pradhan

Reputation: 3295

Here is another approach based on checking if the parameters passed are of type undefined or not.

function add(x, y, z) {
    // Both y, z not given
    if(typeof y === "undefined" &&
       typeof z === "undefined")
        return function (a, b) {
            // b not given
            if(typeof b === "undefined")
                return function (c) { return x + a + c;  };
             else 
                return x + a + b; 
        };
    // Only z not given
    if(!(typeof y === "undefined") && 
         typeof z === "undefined") 
        return function (d) { return x + y + d; };
    return x + y + z;
}

console.log("add(2)(3)(4) = " + add(2)(3)(4)); // 9
console.log("add(2)(3, 4) = " + add(2)(3, 4)); // 9
console.log("add(2, 3)(4) = " + add(2, 3)(4)); // 9
console.log("add(2, 3, 4) = " + add(2, 3, 4)); // 9

Note that the answer given by @Arun is better and more concise.

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388406

I think what you need to do is, once you have processed 3 parameters, you will have to return the sum, not the function

function add() {
  var sum = 0,
    counter = 0;

  function local() {
    [].some.call(arguments, function(value) {
      sum += value;
      return ++counter >= 3;
    })

    return counter < 3 ? local : sum;
  }

  return local.apply(this, arguments)
}

snippet.log(add(10, 5, 2));
snippet.log(add(10)(5, 2));
snippet.log(add(10)(5)(2));
snippet.log(add(10, 5)(2));
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Upvotes: 4

Related Questions