tc39 / proposal-collection-methods

https://tc39.github.io/proposal-collection-methods/
Other
172 stars 8 forks source link

Why not `.reduce`? #3

Open Ginden opened 6 years ago

Ginden commented 6 years ago

From @pitaj on July 31, 2017 2:0

There may be few use cases for reduce on a set, but they do exist. It would serve as extra consistency with Arrays as well.

Copied from original issue: Ginden/set-methods#3

Ginden commented 6 years ago

From @domenic on January 16, 2018 1:42

reduce() is currently included. However, it's a bit strange as it assumes an ordering, which JS sets have, but is not part of the usual concept of a set.

reduceRight() is missing though. I think either neither or both should be included.

Ginden commented 6 years ago

From @pitaj on January 16, 2018 1:47

In my opinion, not having reduce makes more sense, as there's no way to sort a set. As you said, sets don't normally have an order.

I think doing [...set].reduce() is preferable to having reduce on sets.

Ginden commented 6 years ago

I understand your concerns about reduce ordering. I had them too, but since then I was convinced that it totally makes sense to fold (reduce) set, because all iterating methods depend on some implicit "ordering". It should be treated as implementation detail. First element iterated isn't "first element in set" - it's "first element to be iterated over".

Personally I would like to make set iteration implementation-dependent but guaranteed to be stable.

Ginden commented 6 years ago

From @domenic on January 19, 2018 18:0

OK, so why doesn't indexOf(el) exist then? It would tell you what position in iteration order the element appears.

Ginden commented 6 years ago

Because sets aren't indexable, so it would be virtually useless (though, Python provide generic enumerate method anyway). Position in iteration order is "virtual" - it can change anytime (eg. calling .delete method will move other items positions).

Conceptually, position in iteration order shouldn't even matter. And there are many use cases where starting item for .reduce doesn't matter, especially when performed operation is associative (summation is simplest example).

Ginden commented 6 years ago

From @domenic on January 20, 2018 0:50

I don't find the comparison convincing. Calling .splice() will move other items' positions in an array.

If position in iteration order shouldn't matter, then please don't add reduce(), as it's entirely built on that idea. It would indeed be a different story if we had a language with some way to enforce associative-only operations, but we don't, so iteration order is an intrinsic part of the reduce method.

Ginden commented 6 years ago

From @pitaj on January 20, 2018 1:8

It's also worth mentioning that for most associative operations, like sum and product, it's probably better to have Math functions for those specific operations. For instance, Math.sum(...numbers) and Math.product(...numbers). Maybe also Math.mean and Math.median could work on sets of numbers.

Ginden commented 6 years ago

From @tabatkins on January 23, 2018 22:13

If position in iteration order shouldn't matter, then please don't add reduce(), as it's entirely built on that idea.

Strongly disagree. As you note in the following (unquoted) sentence, reduce() on a set completely makes sense if you have commutative+associative reducers, but in reality sets are ordered on the web platform (note that Infra only defines ordered sets for exactly this reason), and so arbitrary reducers make sense just fine.

I do agree that reduceRight() should exist, simply for symmetry. Weird to be able to reduce from one direction but not the other, just because the "normal" direction implies its direction (left) rather than putting it into the name.

I'm ambivalent on .indexOf() - it does have a meaningful definition, but it's useless.

Ginden commented 6 years ago

From @pitaj on January 23, 2018 22:22

We need to decide if the implicit insertion-ordering of Set qualifies as Array-like ordered behavior. If it does, then reduce, indexOf, etc make sense (maybe even sort if it returns a new Set). Otherwise, they should not be included on Set, instead certain analogues by different names can be added (like fold instead of reduce).

zeel01 commented 3 weeks ago

I'm actually having a hard time coming up with an example case for reduce where I would care about the order. In most cases that make sense to use reduce for, I think it unlikely that the order will be meaningful. Perhaps something like Array.prototype.join() implemented as a reduce on a set would be unwise if order isn't as expected, but in what situation is that needed? Also the alternative is [...set].reduce(), which does the same thing but with extra verbose ugly syntax - it still doesn't actually guarantee anything about the order.

Honestly the best argument I can think of for not having this, is that it's questionable that arrays have it in the first place. There are few and far between uses for reduce on an array that are actually simpler and easier to understand than using a loop, and the performance has been shown to be poor. And most uses would be better managed by some other function or combination thereof. Still, I feel like a core part of this proposal is to make collections and arrays more similar, and eliminate the need to constantly convert collections into arrays whenever you want to do anything more complicated than loop over them once. With that goal in mind, I see no strong reason not to include every method that has an even remotely feasible implementation and is at all useful.