Go lacks a nice way to hand around a map iteration state. There are
ways to to this, but they either require handing around a doubly-
wrapped closure
```
func iterator(m map[KT]VT) func(func(v VT)) {
return func(fn func (v VT)) {
for _, v := range m {
fn(v)
}
}
}
```
which does not allow real pausable iteration without additional
callback horror making is essentially useless for public API (where
this is actually useful).
A goroutine based system
```
type iter <-chan VT
func (i iter) next() (VT, bool) {
v, ok := <-i
return v, ok
}
func iterator(m map[KT]VT) iter {
i := make(chan VT)
go func() {
for _, v := range m {
i <- v
}
close(i)
}()
return i
}
```
which requires that the user must drain to complete map or cause a
goroutine leak and has significant performance impacts still.
Or to copy out all the keys and then iterate over them
```
type iter struct {
m map[KT]VT
idx int
keys []KT
}
func (i *iter) next() (VT, bool) {
if i.idx < len(i.keys) {
v, ok := i.m[i.keys[i.idx]]
i.idx++
return v, ok
}
var v VT
return v, false
}
func iterator(m map[KT]VT) *iter {
i := iter{m: m, keys: make([]KT, 0, len(m))}
for k := range m {
i.keys = append(i.keys, k)
}
return &i
}
```
Which may result in significant additional work and allocation and is
fundamentally not lazy.
However, there is an iterator state type in runtime that is made use of in
reflect in the Value.MapKeys method. At the moment this is iterated over in a
single pass allocating a []reflect.Value that is intended to be used in a call
to Value.MapIndex in a manner analogous to the last example above.
Is there a good reason not to provide a map iteration type in reflect to allow
users to avoid that eager work. This would be a closer (though not identical as
is always the case with reflect) approximation to the language's actual range
operator.
For example (signatures only)
```
type MapRange struct {...
func (r *MapRange) Next() bool
func (r *MapRange) Value() Value
func (v Value) MapRange() *MapRange
```
thanks
Dan
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.