I\'m trying to understand how a function works that is run with two parentheses and two parameters. Like so:
add(10)(10); // returns 20
I k
How could I alter that function so it could be run with one set of parameters, or two, and produce the same result?
You can almost do that, but I'm struggling to think of a good reason to.
Here's how: You detect how many arguments your function has received and, if it's received only one, you return a function instead of a number — and have that function add in the second number if it gets called:
function add(a,b) {
if (arguments.length === 1) {
return function(b2) { // You could call this arg `b` as well if you like,
return a + b2; // it would shadow (hide, supercede) the one above
};
}
return a + b;
}
console.log(add(10, 10)); // 20
console.log(add(10)(10)); // 20
I said "almost" above because just because the add
function received only one argument, that doesn't guarantee that the caller is going to call the result. They could write:
var x = add(10);
...and never call the function that x
now refers to.
function add() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
function total() {
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return total;
}
total.toString = function () { return sum };
return total;
}
This will work for any no of arguments and parentheses.
https://medium.com/@imdebasispanda/super-function-with-closure-86a58a9a980b
To extend what both T. J. Crowder and Benjamin Gruenbaum said, libraries like Ramda (disclosure: I'm one of the authors) allow you to convert a simple function like this:
function add(a, b) {
return a + b;
}
into the style under discussion by wrapping it in a call to a curry
function:
var add = R.curry(function add(a, b) {
return a + b;
});
add(3, 5); //=> 8
add(3)(5); //=> 8
var add3 = add(3);
add3(5); //=> 8
The best article I know on this subject is Hugh Jackson's Why Curry Helps. I wrote a more detailed one at Favoring Curry.
Here is a version of curry
somewhat simpler than the one in Ramda. It would do the above and quite a bit more, but doesn't do some of the things that Ramda does with placeholder values:
// here is a function that takes a function and returns a curried version
// of it, that is, a version that performs the sort of partial application
// you describe.
var curry = function(fn) {
// first, we detect how many arguments the function has.
var fnArity = fn.length;
var partialApply = function(args) {
// now, let's create a function that's curried
return function () {
// collect the previous args as the partial, and add the new
// ones you just received
var newArgs = (args || []).concat([].slice.call(arguments, 0));
// if we have "enough" arguments, we don't need any more partial
// application and we can call the function.
if (newArgs.length >= fnArity) {
return fn.apply(this, newArgs);
} else { // else we return a partially applied version
return partialApply(newArgs);
}
};
};
return partialApply([]); // a function is itself partially applied with 0 args
};
In JavaScript, a function can return a function since a function is just another object. A simple implementation is something like:
function add(x){
return function addOther(y){
return x + y;
};
}
This is possible because of closures and first order functions.
This also lets you do partial application, libraries like Ramda utilize this to great extent.
var addThree = add(3)
addThree(5); // 8