Closed
Description
We propose to add the following functions to package maps, to provide good support for code using iterators.
This is one of a collection of proposals updating the standard library for the new 'range over function' feature (#61405). It would only be accepted if that proposal is accepted. See #61897 for a list of related proposals.
All serves as a “source” for iterators.
// All returns an iterator over key-value pairs from m.
func All[Map ~map[K]V, K comparable, V any](m Map) iter.Seq2[K, V] {
return func(yield func(K, V) bool) bool {
for k, v := range m {
if !yield(k, v) {
return false
}
}
return true
}
}
Keys and Values are like All: not terribly useful by themselves but useful as inputs to other iteration adapters.
In particular, we expect that x := slices.Sorted(maps.Keys(m))
will be a common pattern.
// Keys returns an iterator over keys in m.
func Keys[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K] {
return func(yield func(K) bool) bool {
for k := range m {
if !yield(k) {
return false
}
}
return true
}
}
// Values returns an iterator over values in m.
func Values[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[V] {
return func(yield func(V) bool) bool {
for _, v := range m {
if !yield(v) {
return false
}
}
return true
}
}
Insert and Collect serve as “sinks” for iterators.
// Insert adds the key-value pairs from seq to m.
func Insert[Map ~map[K]V, K comparable, V any](m M, seq iter.Seq2[K, V]) {
for k, v := range seq {
m[k] = v
}
return m
}
// Collect collects key-value pairs from seq into a new map
// and returns it.
func Collect[K comparable, V any](seq iter.Seq2[K, V]) map[K]V {
m := make(map[K]V)
Insert(m, seq)
return m
}
Activity
rsc commentedon Aug 9, 2023
This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group
rsc commentedon Aug 30, 2023
Finishing this proposal discussion is blocked on #61405.
gopherbot commentedon Jan 26, 2024
Change https://go.dev/cl/558736 mentions this issue:
maps: add All, Keys, Values, Insert, Collect
earthboundkid commentedon Jan 30, 2024
It is unfortunate that
slices.Sorted(maps.Keys(m))
won't get a length hint from m and may end up doing unnecessary allocations and copies. What if there were alsomaps.SortedKeys(m)
that did the right thing?Merovius commentedon Jan 30, 2024
@earthboundkid ISTM if that is a concern, it should maybe rather be
slices.SortedLength[E any](int, iter.Seq[E])
(modulo name), as any use of "make a sorted slice from an iterator" would suffer the same issue.I get, FWIW, that "get the sorted keys from a map" is a fairly common use case, to try and get deterministic order from the specifically non-deterministic maps. But it still seems a more general problem.
gophun commentedon Jan 30, 2024
maps.Keys could return a sequence implementation with a length hint and slices.Sorted could type assert for that, similar to what some io.Reader functions do.
gophun commentedon Jan 30, 2024
Nevermind, iter.Seq is a concrete type, not an interface.
51 remaining items