It really isnโt a good comparison though, as reduce has a different use case. For instance, reducing an array into a single value would not be possible with map nor filter (hence the name reduce).
It is possible to do what alll three of them do with forEach, if you create a variable holding the result outside of the callback function, but personally I think that looks worse and disconnects the result from the operation.
Since "reducing to a value" is rather ample, i.e. the value could be an array, an object, or whatever some use cases can be supplemented by .map() and .filter().
Regarding the forEach, yep that's true, all of them could be replaced, but reduce is the only one that actually adds complexity and I'd argue it's the one that adds the least value. .map() and .filter() reduce complexity from reading the code, .reduce() adds to it and that's why I don't favor it much. At least, besides simply summations, multiplications, etc I haven't really seen a case where I'd feel it was a good use yet.
Of course, those are examples, and we can find ones in which .reduce() wouldn't harm readability so much as the one above. But for most use cases I've seen in the wild, it does. It simply is harder to read and reason about to a lot of people. That's why even though I can understand it, I steer clear from using it. In general, Code will be read a lot more times than it will be written so even when we have to add one or two extra lines, they are usually easily paid for ten-fold by gains in readability :)
Ofc, .map() and .filter() are very clear on intention
Funny that you say that because .reduce is a really good name. It can be used for many things but the ideal use case it's in the name.
and have a simpler API to grasp.
Sure, both .map and .filter are easier to explain because they focus on individual items and nothing more. Now .reduce is another story, it can transform the entire array into something else so you can say that it has a bigger scope.
About those snippets.
Of course, those are examples, and we can find ones in which .reduce() wouldn't harm readability so much as the one above. But for most use cases I've seen in the wild, it does. It simply is harder to read and reason about to a lot of people.
Showing complex (sometimes bad) examples and putting the blame on .reduce doesn't do anyone a favor. It makes harder for people to see what is good for.
While .reduce() is less readable (unless when used for things that are simple like simple arithmetical operations)
That's what I'm talking about, it doesn't look like you know when it's safe to use. Arithmetical operations are just an example, the pattern that you should be looking for is a function that combines two values of the same type. In the second snippet on logInOrder, that is exactly what happens. We can improve the readability on that snippet if we recognize that pattern.
functionlogInOrder(urls){// fetch all the URLs in parallelconsttextPromises=urls.map(url=>{returnfetch(url).then(resp=>resp.text());});// Combine two promises and log the result of the secondconstchainPromises=(firstTask,secondTask)=>{returnfirstTask.then(()=>secondTask).then(console.log);};// log them in sequencereturntextPromises.reduce(chainPromises,Promise.resolve());}
The first thing we do is stop trying to do everything in one expression. The other thing you might notice is that the callback chainPromises doesn't treat the data like a special snowflake inside a .reduce, it's a generic function that takes two promises and returns a new one. When you add .reduce into the mix it should become clear we are reducing an array of promises into a single promise. That said, I still think this is a bad use case for .reduce because the goal of the function is to produce a side effect, that alone should exclude it as the right tool in this case.
I want to say more but I think this is enough for now. If anyone wants to know more, I wrote about it here: Reduce: how and when.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Almost any use case reduce has is best served by a .forEach or through .map or .filter. Most of the time it's useless complexity
It really isnโt a good comparison though, as reduce has a different use case. For instance, reducing an array into a single value would not be possible with map nor filter (hence the name reduce).
It is possible to do what alll three of them do with forEach, if you create a variable holding the result outside of the callback function, but personally I think that looks worse and disconnects the result from the operation.
Since "reducing to a value" is rather ample, i.e. the value could be an array, an object, or whatever some use cases can be supplemented by
.map()
and.filter()
.Regarding the forEach, yep that's true, all of them could be replaced, but reduce is the only one that actually adds complexity and I'd argue it's the one that adds the least value.
.map()
and.filter()
reduce complexity from reading the code,.reduce()
adds to it and that's why I don't favor it much. At least, besides simply summations, multiplications, etc I haven't really seen a case where I'd feel it was a good use yet.In what way do
.reduce()
add complexity while.map()
and.filter()
reduce it? It would be awesome if you'd care to expand on this. ๐Ofc,
.map()
and.filter()
are very clear on intention and have a simpler API to grasp. e.g.:*Taken from *
While .reduce() is less readable (unless when used for things that are simple like simple arithmetical operations). e.g.
Taken from: developers.google
Of course, those are examples, and we can find ones in which
.reduce()
wouldn't harm readability so much as the one above. But for most use cases I've seen in the wild, it does. It simply is harder to read and reason about to a lot of people. That's why even though I can understand it, I steer clear from using it. In general, Code will be read a lot more times than it will be written so even when we have to add one or two extra lines, they are usually easily paid for ten-fold by gains in readability :)Funny that you say that because
.reduce
is a really good name. It can be used for many things but the ideal use case it's in the name.Sure, both
.map
and.filter
are easier to explain because they focus on individual items and nothing more. Now.reduce
is another story, it can transform the entire array into something else so you can say that it has a bigger scope.About those snippets.
Showing complex (sometimes bad) examples and putting the blame on
.reduce
doesn't do anyone a favor. It makes harder for people to see what is good for.That's what I'm talking about, it doesn't look like you know when it's safe to use. Arithmetical operations are just an example, the pattern that you should be looking for is a function that combines two values of the same type. In the second snippet on
logInOrder
, that is exactly what happens. We can improve the readability on that snippet if we recognize that pattern.The first thing we do is stop trying to do everything in one expression. The other thing you might notice is that the callback
chainPromises
doesn't treat the data like a special snowflake inside a.reduce
, it's a generic function that takes two promises and returns a new one. When you add.reduce
into the mix it should become clear we are reducing an array of promises into a single promise. That said, I still think this is a bad use case for.reduce
because the goal of the function is to produce a side effect, that alone should exclude it as the right tool in this case.I want to say more but I think this is enough for now. If anyone wants to know more, I wrote about it here: Reduce: how and when.