Description
We propose to add the following functions to package slices, 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 index-value pairs in the slice.
// The indexes range in the usual order, from 0 through len(s)-1.
func All[Slice ~[]Elem, Elem any](s Slice) iter.Seq2[int, Elem] {
return func(yield func(int, Elem)bool) bool {
for i, v := range s {
if !yield(i, v) {
return false
}
}
return true
}
}
Backward can be used to replace existing 3-clause loops that iterate backward over a slice manually. This happens fairly often in certain algorithms (for example it happens a lot in the compiler’s SSA code).
// Backward returns an iterator over index-value pairs in the slice,
// traversing it backward. The indexes range from len(s)-1 down to 0.
func Backward[Slice ~[]Elem, Elem any](s Slice) iter.Seq2[int, Elem] {
return func(yield func(int, Elem)bool) bool {
for i := len(v)-1; i >= 0; i-- {
if !yield(i, v[i]) {
return false
}
}
}
}
Values is like All: not terribly useful by itself but useful as a source for other code.
// Values returns an iterator over the values in the slice,
// starting with s[0].
func Values[Slice ~[]Elem, Elem any](s Slice) iter.Seq[Elem] {
return func(yield func(Elem)bool) bool {
for _, v := range s {
if !yield(v) {
return false
}
}
return true
}
}
Append and Collect serve as “sinks” for iterators.
// Append appends the values from seq to the slice and returns the extended slice.
func Append[Slice ~[]Elem, Elem any](x Slice, seq iter.Seq[Elem]) Slice {
for _, v := range seq {
x = append(x, v)
}
return x
}
// Collect collects values from seq into a new slice and returns it.
func Collect[Elem any](seq iter.Seq[Elem]) []Elem {
return Append([]Elem(nil), seq)
}
Sorted and SortedFunc collect an iterator and then sort the contents:
// Sorted collects values from seq into a new slice, sorts the slice, and returns it.
func Sorted[Elem comparable](seq iter.Seq[Elem]) []Elem {
slice := Collect(seq)
Sort(slice)
return slice
}
// SortedFunc collects values from seq into a new slice, sorts the slice, and returns it.
func SortedFunc[Elem any](seq iter.Seq[Elem], cmp func(Elem, Elem) int) []Elem {
slice := Collect(seq)
SortFunc(slice, cmp)
return slice
}