Generators
A function is a generator when its return type is written -> yield T. Calling it does not run the body; it returns a sequence that runs the body a step at a time as values are asked for, most often by a for loop.
fn generate_numbers() -> yield i32 {
for i in 0..10 {
yield i
}
}
for n in generate_numbers() {
std::println(n)
}
Only the written return type makes a generator. A spelled-out -> Yield<T> is an ordinary function that returns a Yield<T> value, and a yield in the body does not turn a function into a generator.
In a generator's body:
yield eproduces the next value.emust convert toT.- Yielding a slice literal is an error: its backing array ends at the suspension, before the caller sees the value.
- A bare
returnends the sequence early.return eis an error, since a generator has no return value. - Falling off the end of the body also ends the sequence. There is no missing-return error.
- A generator with no
yieldat all is valid and produces nothing.
fn first_positive(xs: [i32;]) -> yield i32 {
for x in xs {
if x > 0 {
yield x
return // ok: ends the sequence
}
}
} // ok: falling off the end also ends it
yield is an error (SC111E):
- outside a function;
- inside a closure (closures cannot yield yet);
- in a function not declared
-> yield T.
These functions cannot be generators (SC112E): main, constructors, destructors (op delete), eval functions, C-variadic functions, and functions returning !.
Generator lifetimes
A generator can do one thing an ordinary function cannot: its suspended body keeps references to self and to @inout arguments after the call that created it has returned.
- A loop like
for x in xs.gen()keepsxsalive for the whole loop, so it is safe. - A generator stored in a variable can outlive what it refers to, and then dangles.
Do not keep a generator longer than the object it was created from.
var it = make_list().gen() // the list is destroyed at the end of this statement
for x in it { } // it reads a destroyed list
The current compiler does not report a generator that outlives what it refers to. See Implementation Status.
Special return types
These return type modifiers interact with Kairo's concurrency and type system. Each is covered in detail on its respective page:
| Return type | Description | Details |
|---|---|---|
yield T | Generator: produces a sequence of T values | Generators |
atomic T | Atomic wrapper thread-safe operations | Concurrency |