3 ms·
They just added custom iterators ("range over func") to the language in 1.23 but somehow missed the obvious opportunity to add e.g. maps.SortedByKeys. It's clun
by kbolino 2y ago
They just added custom iterators ("range over func") to the language in 1.23 but somehow missed the obvious opportunity to add e.g. maps.SortedByKeys. It's clunky to write:
for _, k := range slices.Sorted(maps.Keys(m)) {
v := m[k]
_ = v // do something with k and v
}
though, it's not as bad as before:
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
slices.Sort(keys)
for _, k := range keys {
v := m[k]
_ = v
}
- 38 2y ago> maps.SortedByKeys thats what you call overfitting kids
- kbolino 2y agoWhatever you think the best name for it is, it's still missing from the library.
- 38 2y agothe point is you dont need it. by your own admission, it would save literally 0 lines of code from your current example. you need discipline when adding sugar otherwise you can ruin a language.
- kbolino 2y agoI said no such thing. First, it would save one line of code (v := m[k]). Second, it would also allow an optimization. When iterating a map directly, you have both the key and the value at the same time. However, since we iterate only the keys here, we then have to look up the value anew for each key. That takes extra time and, for large maps, will thrash the CPU cache. So the following would be both fewer lines of code and faster: for k, v := range maps.Sorted(m) { // do something with k and v } Making common operations clear and concise is not mere sugar in my opinion. It not only improves the developer experience, it also clarifies the developer's intent, which enables better optimizations, and allows bugs and traps to be addressed in one place, instead of languishing in far-flung places.
- jerf 2y agoI think the problem with putting this into the standard library is that while Go may not be super focused on absolutely top-tier performance, it does generally try to avoid offering things that are unexpectedly slow or unexpectedly allocate large things. A sort-by-keys on the standard map would require allocating a full slice for the keys in the sort routine to do the sort, which would surprise people who expect build-in iterators to not immediately do that. Plus it's in the class of things that's pretty easy to implement yourself now. There's always a huge supply of "but the library could just compose these two things for me". If you stick them all in things get bloated. You could literally have written it in the time it took to write the complaint. You got 80% of the way there as it is, I just tweaked your code a bit to turn it into an iterator: https://go.dev/play/p/agBGl_rT7XS https://go.dev/play/p/agBGl_rT7XS
- 38 2y agoits completely pointless to make this an iterator, because you have to loop the entire map to do so, which kills any benefit of using iterators
- kbolino 2y agoAnd yet slices.Sorted was added which does exactly this already, but only for single-valued iterators.
- deleted 2y ago[deleted]
- randomdata 2y ago> And yet slices.Sorted was added which does exactly this already It does not. slices.Sorted accepts an iterator, but returns a slice. Like the earlier comments point out, Go tries its best to give a reasonable idea of what kind of complexity is involved at the API level. slices.Sorted returning an iterator would mask that. By returning a slice, it makes clear that the entire collection of data needs to be first iterated over as the parent described.