Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a curried javascript function that can be called an arbitrary number of times that returns a value on the very last function call

I'm currently working on a programming problem in my personal time that asks that I make a javascript function that can be called in this manner.

add(1) // 1
add(1)(2) // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15

What I'm having trouble figuring out is how to make it return a value on the very last call.

For example, in order for add(1)(2) to work, then add(1) has to return a function, but according to the instructions add(1) when called by itself will return 1.

I'm assuming one way you can overcome this is to figure out how many times in succession the add function is being called, but I cannot think of a way to achieve that. Does anyone have any hints that can point me in the right direction?

I've read these two articles (1, 2) on function currying and I understand them, but I'm not sure how to do currying when dealing with a variable number of arguments.

like image 637
m0meni Avatar asked Nov 24 '15 19:11

m0meni


2 Answers

It is impossible to curry a variadic function with an unknown number of arguments.

Where add is a variadic function, you could do something like

var add5 = curryN(add, 5);
add5(1)(2)(3)(4)(5); //=> 15

var add3 = curryN(add, 3);
add3(1)(2)(3); //=> 6

There's simply no avoiding this tho because a curried function will continue to return a function until the last argument is received, at which point the computation is run.


The only other option is to create some way to "short-circuit" the arguments and notify the function that the arguments are done being sent. That would require something like

var xadd = curryUntilUndefined(add);
xadd(1)(2)(3)(4)(5)(undefined); //=> 15

Here, the undefined signals the end of the variadic arguments. I don't really recommend this tho because of the other problems it can create for you. Not to mention, it's not particularly nice to look at.

like image 96
Mulan Avatar answered Sep 30 '22 14:09

Mulan


It is not impossible, use valueOf().

function add(initNum) {
    var sum = initNum;
    var callback = function (num) {
        sum += num;
        return callback;
    };
    callback.valueOf = function () {
        return sum;
    };
    return callback;
};
console.log(add(1)(2)==3);            //true
console.log(add(1)(1)+1);             //3
console.log(add(1)(2)(3).valueOf());  //6
like image 37
epascarello Avatar answered Sep 30 '22 12:09

epascarello