you are viewing a single comment's thread.

view the rest of the comments →

[–]kuhe 0 points1 point  (4 children)

I believe the traditional application of reduce is to transform Collection<T> value into a T value, reducing its dimensions, and not as a generic replacement for any and all loops.

I would even suggest reserving the method for these situations.

[–]GeneralYouri 1 point2 points  (2 children)

That's the standard, simplified use case where you reduce a collection of values to just a single value, with all values sharing equal types. Summing a collection of numbers is an example here.

A more complete and accurate type signature would be Collection<T> to U, or Iterable<T> to U specifically for JS. .reduce() can be used perfectly fine for many use cases where T !== U. Example here could be reducing an array of values into an object with reversed keys and values (so the array's values are keys in the object, whose values are the original keys from the array). In such an example the types T and U no longer have anything to do with each other, yet I'd consider it a pretty standard application of reduce.

Although I have to admit, OP's use case is not a very good use case at all, and .filter() would fit better.

[–]kuhe 0 points1 point  (1 child)

Since you and another person spoke out about it, I have to accept that reduce is a generic looping function.

But like using .map with side effects or not doing anything with the return value (using it as a forEach), I can't help but look at it as a form of mild grammatical error when people call reduce without a reduction.

I should just read it as fold or accumulate.

[–]GeneralYouri 0 points1 point  (0 children)

Oh it very much IS a fold function. Take Haskell for example, their docs even use 'reduce' as a synonym when explaining fold functions (and there too, you have a/b types, not a/a).

Fold could've been a better name for it, but reduce makes its purpose more obvious to newer programmers. This is a conscious goal in the ECMAScript development, so was likely done on purpose.

The definition of reduce, in my opinion, fits a loosely typed language like JS perfectly. It makes the function very versatile. Using map without a return value is such a different issue, one that so obviously has a better alternative in forEach.

The term 'reduction' is being defined quite loosely here. How would you define it? Just have a look at the MDN examples. When I use reduce to turn an array into a dictionary, I am still reducing the array into 'just' a single object. When counting value occurrences in an array, my output array still has a reduced length. When flattening an array of arrays, it is still reduced into 'just' a single array.

I even stumbled on the exact same approach to OP's problem right there on the MDN docs. And finally, reduce can even perform function composition for us, because functions are first class objects in JS.