Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Passing and returning generators

Use Generator[T] to accept or return a generator:

def once(n: i64) -> Generator[i64]:
    yield n

def pair() -> Generator[i64]:
    yield 10
    yield 20

def source(n: i64) -> Generator[i64]:
    once(n)

def total(values: Generator[i64]) -> Result[i64, OverflowError[i64]]:
    mut result = 0
    for value in values:
        result = result + value
    Ok(result)

def main() -> Result[(), IoError | OverflowError[i64]]:
    print(total(source(7))?)?
    print(total(pair())?)?
    Ok(())
7
30

total accepts either producer. Passing a generator transfers ownership; use &mut Generator[T] when a helper should advance an existing owner with next. Once you know closures, Transform a stream of values shows how to filter, map and reduce a generator without writing the loop.

A factory must return the same producer on every path. Two generators yielding the same type are not interchangeable return values:

def one() -> Generator[i64]:
    yield 1

def two() -> Generator[i64]:
    yield 2
    yield 3

def choose(flag: bool) -> Generator[i64]:
    if flag:
        return one()
    two()

def main() -> ():
    drop(choose(True))
expected Generator[i64] from `one`, got Generator[i64] from `two`

Put such a branch inside one generator body instead. A generator may contain another generator, but recursive generator state is rejected: its inline storage would have no finite size.