Coroutine Pipelines

Wikipedia: Pipeline
Because coroutines implement the iterable protocol, they can be chained into lazy pipelines — each stage consumes one coroutine and produces another, with no intermediate arrays allocated.

fmt := import("fmt")
coro := import("coro")
numbers := func(n) {
    return coro.new(func(yield) {
        for i := 1; i <= n; i++ {
            yield(i)
        }
    })
}
filter_c := func(src, pred) {
    return coro.new(func(yield) {
        for _, v in src {
            if pred(v) { yield(v) }
        }
    })
}
map_c := func(src, f) {
    return coro.new(func(yield) {
        for _, v in src { yield(f(v)) }
    })
}
take := func(src, n) {
    result := []
    for _, v in src {
        result = append(result, v)
        if len(result) >= n { break }
    }
    return result
}
pipeline := map_c(
    filter_c(numbers(10), func(x) { return x % 2 == 0 }),
    func(x) { return x * x }
)

for _, v in pipeline {
    fmt.println(v)
}
naturals := coro.new(func(yield) {
    i := 1
    for { yield(i); i++ }
})

odds := filter_c(naturals, func(x) { return x % 2 != 0 })
fmt.println(take(odds, 5))

try it

4
16
36
64
100
[1, 3, 5, 7, 9]
loading…