lazy iterables in go
package main | |
import ( | |
"fmt" | |
"math/rand" | |
) | |
type DataSource interface { | |
Next() Element | |
} | |
type Element interface { | |
DataSource | |
Val() uint32 | |
} | |
type LazyList struct { | |
ds DataSource | |
val uint32 | |
next Element | |
} | |
func (l *LazyList) Val() uint32 { | |
return l.val | |
} | |
func (l *LazyList) Next() Element { | |
if l.next == nil { | |
l.next = l.ds.Next() | |
} | |
return l.next | |
} | |
func NewLazyList(ds DataSource) DataSource { | |
return &LazyList{ds, 0, nil} | |
} | |
type Predicate func(Element) bool | |
type LazyFilter struct { | |
ds DataSource | |
val uint32 | |
next Element | |
pred Predicate | |
} | |
func (l *LazyFilter) Val() uint32 { | |
return l.val | |
} | |
func (l *LazyFilter) Next() Element { | |
if l.next == nil { | |
r := l.ds.Next() | |
for r != nil { | |
if l.pred(r) { | |
l.next = &LazyFilter{r, r.Val(), nil, l.pred} | |
break | |
} | |
r = r.Next() | |
} | |
} | |
return l.next | |
} | |
func NewLazyFilter(ds DataSource, pred Predicate) Element { | |
return &LazyFilter{ds, 0, nil, pred} | |
} | |
func main() { | |
incr := Incrementor(0) | |
even := NewLazyFilter(incr, func(e Element) bool { | |
return (e.Val() % 3) == 0 | |
}) | |
deca := NewLazyFilter(even, func(e Element) bool { | |
return (e.Val() % 10) == 0 | |
}) | |
rang := NewLazyFilter(deca, func(e Element) bool { | |
return e.Val() < 200000000 && e.Val() > 2200000 | |
}) | |
feed := NewLazyList(rang) | |
strt := feed.Next() | |
cnt := 0 | |
for elem := strt; cnt <= 40; elem = elem.Next() { | |
fmt.Println(elem.Val()) | |
cnt++ | |
} | |
} | |
type Increment uint32 | |
func (i Increment) Val() uint32 { return uint32(i) } | |
func (i Increment) Next() Element { return Increment(rand.Uint32()) } | |
func Incrementor(val uint32) DataSource { return Increment(val) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment