Added the Appendix section on .
I've been thinking about map
and reduce
lately. Nothing too erudite though. Something that I have realised is that it's sometimes too easy to conflate the two into just the reduce
, when instead it might be clearer to have a very dumb map
followed by a very dumb reduce
.
Here's a simple example:
It's not obvious at first, but that reduce
is doing a the job of a map
as well as its own:
- Map: it generates new data for each element of the list (the empty arrays
[]
). - Reduce: it aggregates the data into a new piece of data (the resulting object).
These can be separated as follows:
This is longer to write, but I think it makes the reduce
more readable by turning it into a common idiom, a "pairs to object" reduction if you will. With that in mind you can focus separately on the mapping function and possibly understand better what's being produced.
Functional programming tools can help me explain better. For example, using Ramda I could implement the above as follows:
With the use of R.fromPairs
in this example, we have turned the "pairs to object" idiom into a single, self-describing function invocation. Now that's easy to read. Compare to the Ramda version of the initial code:
I think now the separation between map
and reduce
becomes more apparent, and so does the benefit of enforcing it.
Appendix
After I first published this post, I discussed this topic with my friend Rosario. He reminded me that map
, filter
, forEach
, and all those fellows are just special cases of reduce
. For example:
Thinking about this, I reached another conclusion: don't use reduce
unless you must. It's possible that your library has already a function that will implement what you need. Some other special case of reduce
, same as Ramda's R.fromPairs
filled my reduction needs above. Use that instead. It will be easier to read and understand, both by means of saving you a few braces and brackets as well as by providing a more descriptive name.
And if you don't have such a reducer at hand, create one. A descriptively named function, tailored to your use case. Wrap the reduce
in a named piece of code and use that instead of sticking it in a longer chain that may be already difficult enough to follow. Like that long sentence I just wrote.