Currying is indeed a very interesting topic of functional programming more about it on wikipedia. @honmanyau for example asked what the “proper” way to do this would be.
My approach is more “proper” with respect to the examples in the other posts in the sense that it is a generalized form of @marinm’s mysterious()
function compared to the previous solutions.
I am first going to assume that there is such a function (without explicitly defining it. That comes later) called curry()
(the equivalent of the original poster’s mysterious()
function) and that this function must satisfy a certain set of properties in order to work as desired.
Before we continue let us first define some things for later.

pure function
:
A pure function is a function that when called, introduces no side effects. That means the following.
Given the same input the function will always return the same output regardless of the global program state.
The global programm state at the point before calling the function will be the same after calling the function.
This means that the function does not alter any global state.

arity
:
The number of arguments that a function f expects is called the arity of f.
For example.
function add(a, b) {
return a + b;
}
Here the function add()
has an arity of 2.

fixed arity
:
The number of arguments that a function expects is fixed and not dynamic.
function foo(a) {
if(arguments.length === 1) {
return a * 2;
}
else if(arguments.length === 2) {
return a * 2 + arguments[1] * 2
}
}
Here foo()
does not have a fixed arity. add()
from the previous example does.

f(a)(b)(c)
:
This is referred to as calling f in the curried form.

f(a, b, c)
:
This is referred to as calling f in the list form.
Now let us state the properties that our mysterious function has to fullfill and then define such a function later on.
This approach is going to look rather rigorous (but don’t panic it’s easier than it looks)
Let F
be an arbitrary pure function with fixed arity. Then there is another function let’s call it curry()
that when applied on F
returns a new function let’s call it f
with f = curry(F)
that satifies the following properties.
We can also apply that property partially (i.e not with all arguments at once) and a multiple number of times
For example it could look like one of these.
If F
has arity n
then f
can be called p
times with 0 < p <= n
(either in list form or curried form) with k
split points (k = p  1
) where a split point is (see example formulas above) when we change from list invocation to curried invocation or the other way around (from curried to list). We refer to each of those “times” (the p
times) as a call interval i
. The first interval is i1
then i2
, i3
, … up until ip
the pth call interval. Each interval can have an arbitrary length (i.e involves an arbitrary number of arguments) with the following constraints.
Further for any interval we have:
In this constraint k
does not refer to the number of split points but just to any arbitrary interval that lies between 1 and p
.
The following formulas give a full generalisation of the previous examples depending on wether you start out in the curried form or in the list form.
Calling in curried form first:
Calling in list form first:
So that’s it from a theoretical standpoint. The implementation is something else. A Javascript implementation might look similiar to this (spoiler! click to see).
function curry(fn) {
var slice = Array.prototype.slice;
var arity = fn.length;
var args = slice.call(arguments, 1);
function acc() {
var largs = args;
if (arguments.length > 0) {
largs = largs.concat(slice.call(arguments, 0));
}
if(largs.length >= arity) {
return fn.apply(this, largs);
}
else {
return curry.apply(this, [fn].concat(largs));
}
};
return args.length >= arity ? acc() : acc;
};
There are some things one must be aware of when implementing this in javscript (works with fixed arities only!). We could also make a deep copy of the arguments instead of a shallow one. The following article explains it in much more detail. The implementation above is also more or less from it as after all that I was to tired to try my own solution. At last I made a small gist so you can see a small application/demo of our newly discovered function.
I put this post together after doodling around for the afternoon on these concepts. Let me know if you see any logical mistakes or errors in general so I can fix them.