Implicit Function Chaining in Lodash
A couple of days ago, I blogged about how nicely ECMAScript 2015 works together with Lodash and Underscore. In this post, I gave a little code example showing how to build a function chain to transform some array data. Map and reduce, nothing too fancy.
Coming from Underscore, I was used to constructing function chains by explicitly calling the
_.value functions which start and end a function chain, respectively. To my surprise, I learned from John-David Dalton that for cases like mine, calls to
_.value aren't required because Lodash has implicit function chaining. Let's look at an example.
Suppose you have array of numbers and want to calculate the sum of squares of all even numbers. Using ECMAScript 2015, you could construct the following function chain to solve the problem:
let numbers = [1, 2, 3, 4, 5]; let sumOfEvenSquares = _.chain(numbers) .filter(n => n % 2 === 0) .map(n => n * n) .sum() .value(); // sumOfEvenSquares: 20
The above code calls the
_.value functions and thus sets up an explicit function chain. This chain is already pretty easy to read, but it can be simplified further.
Instead of creating an explicit function chain, we can pass
numbers as an argument to the global Lodash function to start an implicit one. By doing that, we can omit the call to
_.value at the end of the chain:
let sumOfEvenSquares = _(numbers) .filter(n => n % 2 === 0) .map(n => n * n) .sum();
Because our calculation ends with a call to
_.sum which returns a plain number, Lodash "intuitively" terminates the function chain. This happens for all Lodash functions that perform a reduction to a single value, but not for transformation functions like
_.map that don't necessarily represent the end of a function chain.
Now that the code has become even shorter, it easily fits into a single line without being hard to read. If you prefer, you could write the computation like this as well:
let isEven = n => n % 2 === 0; let square = n => n * n; let sumOfEvenSquares = _(numbers).filter(isEven).map(square).sum();
For more details, check out the "Chain" Methods section in the Lodash documentation.