This probably looks a bit confusing because I don't think it's explained very well. Or, rather, I don't think it's explained in a typical JavaScript way.
Let's break down the examples
First Example
Breakdown
var calculateCircumference = (diameter) => (
(PI) => diameter * PI)(3.14159265)
);
calculateCircumference(2); // 6.2831853
Arranged like this, here is what happens if you call this code
- You pass the diameter (e.g., 2)
- A new function is created that takes
PI as parameter and uses it to calculate the circumference. This function is immediately invoked
- The function uses both variables present to do the calculation
Aside from being wasteful computation-wise (two invocation) this example is also convoluted for no good reason. The inner function is pointless and doesn't gain you anything. It's probably where the example loses lots of its clarity - seems like the only reason to have the example work as it is, is to set up for the second example.
Second Example
On currying
Before tackling the example, it seems like the book probably failed to mention how exactly it works. The second example leverages a technique called curry which is used in functional programming - it is not specific to JavaScript but it is still widely known as that name in the JavaScript world. A very brief overview of currying
//non-curried
function add(a, b) { // or, in ES6: (a, b) => a + b;
return a + b;
}
//curried
function curryAdd(a) { //or in ES6: (a) => (b) => a + b;
return function(b) {
return a + b;
}
}
//invocation
add(2, 3); // 5
curryAdd(2)(3); // 5
I will not go into detail but essentially, a curried function that takes multiple parameters, can be passed less and it will return a new function that can take the rest. When all the parameters are satisfied, you will get the result - in a formal notation, the curryAdd function will be expressed as curryAdd :: Number -> Number -> Number - it's a function that takes a number and returns another function that takes a number which finally returns another number. For why you would want to do that, here is an example - it's trivial but it gets the point accross:
//add5:: Number -> Number
add5 = curryAdd(5);
add5(3); // 8
add5(10); // 15
[1, 2, 3].map(add5); // [6, 7, 8]
Currying is a bit like partial allocation of functions but the two are not (necessarily) the same thing.
Breakdown
With that said, let's look at the second example:
//curryMultiply :: Float -> Float -> Float
(PI) => (diameter) => diameter * PI
//another way to write it:
//(a) => (b) => a * b
Hopefully that clarifies what is going on a bit. I'll re-write the rest of the example into what is actually happening:
// calculateCircumference :: Float -> Float
var calculateCircumference = curryMultiply(3.14159265);
calculateCircumference(2); //6.2831853
The second example's code is equivalent to the above. It avoids invoking a function twice because the outer function (which I dubbed curryMultiply) is invoked only once - any time you call the calculateCircumference function, you are only evaluating the inner function.
Math.PI...