type stop int
const (
StopAtMin stop = iota
StopAtMax
)
type eacharray struct {
itrs []i.Forward
err error
stopAt stop
}
func EachArray(stopAt stop, itrs ...i.Forward) i.Forward {
return &eacharray{itrs: itrs, stopAt: stopAt, err: nil}
}
The constructor takes an enum to control the behaviour vis-a-vis the length of individual streams, and a list of iterators.
func (i *eacharray) Value() interface{} {
ret := make([]interface{}, len(i.itrs))
for idx, itr := range i.itrs {
if !itr.AtEnd() {
ret[idx] = itr.Value()
} else {
ret[idx] = nil
}
}
return ret
}
func (i *eacharray) Error() error {
return i.err
}
func ( *eacharray) SetError(err error) {
i.err = err
}
The Value() function loops over all iterators, collecting a value from each of them. If the iterator is at end, we use a nil value for that iterator.
func (i *eacharray) Next() error {
for _, itr := range i.itrs {
if !itr.AtEnd() {
err := itr.Next()
if err != nil {
i.err = err
break
}
}
}
return i.err
}
func (i *eacharray) AtEnd() bool {
atEndCount := 0
for _, itr := range i.itrs {
if itr.AtEnd() {
if i.stopAt == StopAtMin {
return true
}
atEndCount++
}
}
return atEndCount == len(i.itrs)
}
The Next() method loops over all iterators, calling Next() on each iterator that is not at end yet. The AtEnd() method loops over all the iterator and checks each one for EOS. If stopAt is StopAtMin, we return true on first EOS we encoundter, otherwise we return false until all iterators return EOS.
itr := EachArray(
StopAtMax,
i.List(1, 2, 3, 4, 5, 6),
i.List(6.4, 7.1, 8.2, 9.9),
i.List("A", "B", "C", "D", "E"))
for ; !itr.AtEnd(); itr.Next() {
fmt.Println(itr.Value())
}
Usage is simple and there is no need for all the lists to be of the same type.
Get the source at GitHub. It is also available in the iterator library as Zip.
No comments:
Post a Comment