When interviewing candidates,
they had used and let them implement one of the methods on paper,
If someone knows that functions can be passed around,
this should not be a hard task.
reduce function was most rarely mentioned.
Last week Sophie Alpert tweeted about
her rule for the
reduce function. There was then a hot discussion,
as the last two rules in the list were controversial among many people.
my rule for .reduce(): only use it when the result has the same type as the items and the reducer is associative, like— Sophie Alpert (@sophiebits) February 22, 2019
.reduce((a, b) => a + b, 0)
✅ summing some numbers
✅ multiplying some numbers
🚫 building up a list or object
🚫 just about anything else (use a loop)
I myself use this function a lot. Not only for summing and multiplying numbers, but also for composing a new array or object. Sophie's rule made me think about this function again.
Reduce vs Fold
Reduce is a higher-order function which is usually called
in functional programming languages.
fold is definitely
a better name compared to
since this's how it behaves like folding a fan in my head.
It also has directions,
reduce traverses a list from left to right,
reduceRight does from the other direction.
You've probably seen
foldr somewhere else,
they're the same thing but much readable.
the first element in the given array will be used.
That's why I prefer
foldr1 in other languages like Haskell,
which explicitly uses the first or last element as initial value.
There are two simple tasks by given the following data, and solutions with normal loops:
a) Get the total score of all items.
b) Get the item with the highest score.
The above two functions have something in common:
- An initial value.
- A rule on how to update the initial value with each item in the list.
- Returns the final updated value.
We can define a function to abstract the repeated pattern.
This is actually a simple version of
Now rewrite the solutions to see how they will look like with
Once you identify this pattern, the code will be more understandable. The benefit of the abstraction is that the rule can be separated and possibly be reusable.
getHighest() also have a different place.
getScoreSum()returns a number.
getHighest()returns an object, the type is same with items in the list.
Normally it's called asymmetrical in its types when the type of the returned value is different from the type of items in the list. Otherwise, it is symmetrical.
The first two rules in Sophie's tweet basically referred to symmetrical functions.
Sometimes it's convenient to make the first element as the initial value when it's symmetrical.
Also, we could reduce one iteration in the loop. So here are little modifications to the
function we just defined.
Much simpler now:
Building up a list
With the normal loop:
Again, we see the pattern exposes.
So let's try to do it with
As you can see it's not that bad. We can go further to support flattening on deep nested array:
Some other functions can also be implemented with
We can do this as a practice regardless of some performance concerns.
Abstractions are ways of thinking.
If the performance is not crucial I still prefer to use
reduce function whenever appropriate.
Because it allows me to focus on the most important part and write less code.