Skip to content

Generators

Calibre uses gen:<T> for generators.

A generator can yield values over time instead of building a whole list at once. Allowing for potentially infinite series to be represented

Note that all generator functions must have an explicit return type of gen:<T>

const count_up := fn (start : int, end : int) -> gen:<int> => {
let mut i := start;
for i < end => {
if i % 2 = 0 => return i; // Note that return basically acts as the yield keyword in other languages.
i += 1;
};
};

Inside a generator function, return value; produces the next generated item. A plain return; or the end of the function scope ends the generator.

You can pull values from a generator with .next() as they inherent the Iter trait.

let mut g := count_up(0, 10);
print(g.next());
print(g.next());
print(g.next());

You can also iterate through generator results in a loop.

let mut g := count_up(0, 10);
for let .Some : value <- g.next() => print(value);

Generators are useful when values should be computed lazily, or when you want to represent a sequence without allocating the whole result up front.