The Challenge:
1 2 3 4 5 6 7 8 9 10 11 
Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum. For example, addTogether(2, 3) should return 5, and addTogether(2) should return a function. Calling this returned function with a single argument will then return the sum: var sumTwoAnd = addTogether(2); sumTwoAnd(3) returns 5. If either argument isn't a valid number, return undefined. 
The solution should return:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 
addTogether(2, 3) should return 5. addTogether(2)(3) should return 5. addTogether("http://bit.ly/IqT6zt") should return undefined. addTogether(2, "3") should return undefined. addTogether(2)([3]) should return undefined. 
Some helpful links:
Is possible to reduce the complexity and spaghetti quality of this Javascript algorithm solution?
Starter Code:
1 2 3 4 5 
function addTogether() { return false; } addTogether(2, 3); 
This challenge threw me for a loop. It ended up that I simply didn’t understand what it was telling me to achieve. I thought that I shouldn’t add any parameters to function addTogether(), and tried a slew of different things involving if statements and nested if statements, but got nowhere. It consisted of a lot of nonfunctioning spaghetti code! I finally went into the Free Code Camp Wiki for this algorithm to check out what solution was posted there. This is what I found:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 
function addTogether() { // check if argument(s) valid number var validateNum = function(num) { if (typeof num !== 'number') { return undefined; } else return num; } ; // is there is one argument or two if (arguments.length > 1) { var a = validateNum(arguments[0]); var b = validateNum(arguments[1]); if (a === undefined  b === undefined) { return undefined; } else { return a + b; } // if only one argument, return function that expects one argument and returns sum. } else { var c = arguments[0]; // start here if (validateNum(c)) { return function(arg2) { if (c === undefined  validateNum(arg2) === undefined) { return undefined; } else { return c + arg2; } }; // belongs to return function(arg2) {} } } } addTogether(2)(3); 
It does work. All actual outcomes === expected outcomes, but I couldn’t make heads or tails of it. I had spent days trying to figure this one out. For example, the first else statement was missing an opening curly bracket. However, if I added one, the code broke. I checked the code in JSHint and the metrics were the following:
1 2 3 4 5 6 7 
There are 3 functions in this file. Function with the largest signature take 1 arguments, while the median is 1. Largest function has 10 statements in it, while the median is 3. The most complex function has a cyclomatic complexity value of 5 while the median is 3. 
The complexity was not too terrible because there were no for loops, for example. Only if else statements nested in if else statements. Perhaps I’m not a seasoned Javascript developer, but I thought there had to be a better way.
I finally decided to take the StackOverflow plunge and ask for help with the algorithm, and specifically to detangle this solution.
I have to say, I was a bit nervous about posting a question. I use StackOverflow a lot, and I was sure that I would be struck down. Quite the opposite happened, however! It taught me a lesson. Just don’t be afraid to put your first foot forward. And what’s the worst that can happen anyway? You’re told it’s a duplicate question. You’re told it’s not an appropriate question to ask on StackOverflow. You’re told it’s a stupid question (there are no stupid questions). If you don’t have the skin to take it, then are you pursuing the right thing?
This was my question: Is it possible to reduce the complexity and spaghetti quality of this JavaScript algorithm solution?
Aside from the fact that someone suggested that the question would have been more appropriate for codereview.stackexchange.com, I immediately started to get feedback and answers. I had been considering posting it on Code Review, but I probably wouldn’t have gotten the kind of answers I wanted there.
The answer which I liked the best (and was also the first) was the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
function addTogether(a, b) { if (typeof a == "number") { if (arguments.length == 1) { return b => addTogether(a, b); } else if (typeof b == "number") { return a + b; } } } // as per OP's code // returns 3 console.log("addTogether(1, 2) = " + addTogether(1, 2)); console.log("addTogether(1, 2, 3) = " + addTogether(1, 2, 3)); console.log("addTogether(1)(2) = " + addTogether(1)(2)); console.log("addTogether(1)(2, 3) = " + addTogether(1)(2, 3)); console.log("addTogether(1, 2, '3') = " + addTogether(1, 2, '3')); console.log("addTogether(1)(2, '3') = " + addTogether(1)(2, '3')); console.log("addTogether(1, 2, [3]) = " + addTogether(1, 2, [3])); console.log("addTogether(1)(2, [3]) = " + addTogether(1)(2, [3])); console.log("addTogether(1, 2, NaN) = " + addTogether(1, 2, NaN)); console.log("addTogether(1)(2, NaN) = " + addTogether(1)(2, NaN)); // returns NaN console.log("addTogether(1, NaN) = " + addTogether(1, NaN)); console.log("addTogether(1)(NaN) = " + addTogether(1)(NaN)); // returns undefined console.log("addTogether() = " + addTogether()); console.log("addTogether(1)() = " + addTogether(1)()); console.log("addTogether('1') = " + addTogether('1')); console.log("addTogether(1, '2') = " + addTogether(1, '2')); console.log("addTogether(1)('2') = " + addTogether(1)('2')); console.log("addTogether(1, [2]) = " + addTogether(1, [2])); console.log("addTogether(1)([2]) = " + addTogether(1)([2])); 
The code was written in ES6. Since the Free Code Camp editor is made for ES5, I transpiled the code to ES5 in the Babel repl. Interestingly enough, however, when I did this, the ES5 code did not work. Originally I thought it had something to do with the solution in ES6 not translating well into ES5. I made a few tweaks to the ES5 code:
1 2 3 4 5 6 7 8 9 10 11 
function addTogether(a, b) { "use strict"; if (typeof a === "number" && arguments.length === 1) { return function(b) { return addTogether(a, b); }; } else if (typeof b === "number") { return a + b; } } addTogether(2, 3); 
Then it worked. First of all, I didn’t like the idea of == instead of ===. Second of all, I didn’t see the need for nested ifs when && produced the same result. Note: I went back to check out whether the original code provided still “didn’t work”. Now it did. This will perhaps remain a mystery! I still would have gone with the tweaks, however. The code is even clearer, and even more succinct. And even though someone had pointed out that the first if statement contained nested functions, I am okay with that as well. It is totally on target for what I needed to achieve with this algorithm, and it visually makes sense.
What my solution should achieve:
 Should create a function that sums two arguments together.
 If only one argument is provided, then return a function that expects one argument and returns the sum (of two).
As for JSHint Metrics, these are the metrics for the original answer:
1 2 3 4 
There are 2 functions in this file. Function with the largest signature take 2 arguments, while the median is 1.5. Largest function has 4 statements in it, while the median is 2. The most complex function has a cyclomatic complexity value of 4 while the median is 2.5. 
JSHint Metrics for the solution including my tweaks:
1 2 3 4 5 6 7 
There are 2 functions in this file. Function with the largest signature take 2 arguments, while the median is 1.5. Largest function has 3 statements in it, while the median is1.5. The most complex function has a cyclomatic complexity value of 3 while the median is 2. 
 I have learned a lot since I originally tried tackling this algorithm. I learned a lot sharing my woes on StackOverflow. It is so important to discuss code with others. Take every opportunity to do so! I know I probably should be doing more sharing there than I have to date, or elsewhere if given opportunities.
Let’s break down the final solution and analyze what is going on:
Let’s analyze the expected outcomes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 
addTogether(2, 3) should return 5. addTogether(2)(3) should return 5. addTogether("http://bit.ly/IqT6zt") should return undefined. addTogether(2, "3") should return undefined. addTogether(2)([3]) should return undefined. 
4 out of 5 outcomes involve numbers in at least one of the arguments. 2 of the expected outcomes involve numbers in both arguments. One expected outcome involves no numbers. Two expected outcomes involve a non number in the second argument. One expected outcome involves no numbers.
The concept that I got hung up on, and that probably the creator of the code in the Wiki did as well, was what “optional arguments” implied. I thought, and perhaps he/she did too (because of the lack of parameters in the code), was that “optional arguments” meant you should omit function parameters. That is what I originally thought. I had searched high and low for a definitive answer to that question. Some people who commented on my question on StackOverflow were initially under that impression as well. I have learned since, that it isn’t a matter of omitting parameters in the function, it’s a matter of providing the option of one argument or 2. Looking back, I don’t remember why I thought the way I did. Probably based on information I did manage to gather. Well, I was wrong. It is about optional arguments after all, and not optional parameters!
Getting back to the code…
 This is actually a pretty clever and cool solution. function addTogether(a, b) takes two parameters, which is the max number of possible provided arguments.
 I create the base case for if there is one provided argument, that the argument represents parameter a and is a number:
1234if (typeof a === "number" && arguments.length === 1) {return function(b) {return addTogether(a, b);};  If a is a number and there is only one provided argument, return function (b),
representing a second argument. Returning function (b) brings into existence the second argument.  Then return the recursive call to function addTogether(a, b). Because addTogether(a, b) is returned within the anonymous function(b), which is also returned from parent function addTogether(a, b), addTogether(a, b) is equivalent to adding a and b together. However, it is not exactly the same. If I had simply returned a + b instead of addTogether(a, b), it would have resulted in “23”. But by returning addTogether(a, b) recursively, it is resulting in the sum of a and b instead of the concatenation of a and b resulting in a string.
 But what about if there are two arguments? That’s where the else if statement comes in:

123} else if (typeof b === "number") {return a + b;}
 So if arguments.length !== 1, meaning there are two arguments, and b is a number, return a + b. This implies that both a and b are numbers. Only one set of provided arguments fits this scenario: addTogether(2, 3). a + b results in a real number and not a string.
 In the fourth and fifth set of provided arguments, b is not a number, and the solution returns undefined.
 The third provided argument, which is just 1 argument, when there should be two in some form, returns undefined for two reasons. One is that there is only 1 argument, and therefore no sum of two. Second of all, it is not a real number. It is a string.
 expected outcomes === actual outcomes.
JSHint Metrics:
1 2 3 4 
There are 2 functions in this file. Function with the largest signature take 2 arguments, while the median is 1.5. Largest function has 3 statements in it, while the median is 2. The most complex function has a cyclomatic complexity value of 3 while the median is 2. 
Solution:
1 2 3 4 5 6 7 8 9 10 11 
function addTogether(a, b) { "use strict"; if (typeof a === "number" && arguments.length === 1) { return function(b) { return addTogether(a, b); }; } else if (typeof b === "number") { return a + b; } } addTogether(2, 3); 
Solution in ES6:
1 2 3 4 5 6 7 8 
function addTogether(a, b) { if (typeof a === "number" && arguments.length === 1) { return b => addTogether(a, b); } else if (typeof b === "number") { return a + b; } } addTogether(2, 3); 
Comment Policy: Your words are your own, so be nice and helpful if you can. Please, only use your real name and limit the amount of links submitted in your comment. We accept clean XHTML in comments, but don't overdo it please. Comments are moderated, so spammy or malicious links will be removed.