Easy

mul(a)(b)(c)

Prompt

Write a JavaScript function called mul that multiplies three numbers using currying. Instead of taking all three arguments at once like mul(1, 2, 3), the function should be called one argument at a time.

mul(1)(2)(3); // Returns 6
mul(5)(5)(5); // Returns 125

Playground

Hint 1

mul(2) needs to return something that can be called with (3). What kind of value in JavaScript can be "called"?

Hint 2

Each call returns a function that remembers the previous arguments through closure. The innermost function has access to all three values and can finally compute the result.

Solution

Explanation

Normally when you multiply three numbers, you'd write something like multiply(1, 2, 3) and pass all three at once. Currying flips that around. You pass one number at a time: mul(1)(2)(3).

But what does mul(1)(2)(3) actually mean? Let's read it slowly.

mul(1) is a function call. It doesn't give you a number back. It gives you back a function. Then you call that function with (2). That also gives you back a function. And then you call that function with (3), which finally gives you the answer: 6.

So when you see mul(1)(2)(3), think of it as three separate calls happening one after another:

const step1 = mul(1); // returns a function
const step2 = step1(2); // returns another function
const step3 = step2(3); // returns 6

Writing mul(1)(2)(3) is just a shorthand for the above.

The solution

const mul = (a) => {
return (b) => {
return (c) => {
return a * b * c;
};
};
};

It's functions inside functions inside functions. mul takes a and returns a function. That function takes b and returns another function. That function takes c and finally computes a * b * c.

But wait, how does the innermost function know about a and b? They were passed to completely different functions. This is where closures come in. In JavaScript, a function always remembers the variables from the place where it was created. The innermost function was created inside the function that has b, which was created inside the function that has a. So it can see all of them.

Shorter syntax

You can write the whole thing as a one-liner:

const mul = (a) => (b) => (c) => a * b * c;

Arrow functions without curly braces automatically return, so this does the exact same thing in less code.