# A generator statement creates a generator factory. The
# following generator yields two times and then returns `"c"`:
generate_abc <- generator(function() {
yield("a")
yield("b")
"c"
})
# Or equivalently:
generate_abc <- generator(function() {
for (x in letters[1:3]) {
yield(x)
}
})
# The factory creates generator instances. They are iterators
# that you can call successively to obtain new values:
abc <- generate_abc()
abc()
abc()
# Once a generator has returned it keeps returning `exhausted()`.
# This signals to its caller that new values can no longer be
# produced. The generator is exhausted:
abc()
abc()
# You can only exhaust a generator once but you can always create
# new ones from a factory:
abc <- generate_abc()
abc()
# As generators implement the coro iteration protocol, you can use
# coro tools like `loop()`. It makes it possible to loop over
# iterators with `for` expressions:
loop(for (x in abc) print(x))
# To gather values of an iterator in a list, use `collect()`. Pass
# the `n` argument to collect that number of elements from a
# generator:
abc <- generate_abc()
collect(abc, 1)
# Or drain all remaining elements:
collect(abc)
# coro provides a short syntax `gen()` for creating one-off
# generator _instances_. It is handy to adapt existing iterators:
numbers <- 1:10
odds <- gen(for (x in numbers) if (x %% 2 != 0) yield(x))
squares <- gen(for (x in odds) yield(x^2))
greetings <- gen(for (x in squares) yield(paste("Hey", x)))
collect(greetings)
# Arguments passed to generator instances are returned from the
# `yield()` statement on reentry:
new_tally <- generator(function() {
count <- 0
while (TRUE) {
i <- yield(count)
count <- count + i
}
})
tally <- new_tally()
tally(1)
tally(2)
tally(10)
Run the code above in your browser using DataLab