Do not wait for Rust generators
What is generator?
Generators are a pattern widely used in the Python ecosystem, like iterators, they are very useful to produce multiple values. But unlike iterators, they work by interrupting the execution of the function, and allows the caller to resume its execution later:
yield keyword interrupts the function and produce the supplied value. Now, instead of using the
next() function to resume the generator, you can use:
yieldkeyword will return
yieldkeyword will throw
gen.close(): the generator won’t resume (and raise a
NB: This is also called a coroutine.
They are a powerful tool. In fact, they were used for concurrency before the rise of
Unfortunately, at the time of writing, this is still an unstable feature in Rust.
GitHub - whatisaphone/genawaiter: Stackless generators on stable Rust.
This crate implements stackless generators (aka coroutines) in stable Rust. Instead of using yield, which won't be…
This crate gives you, thanks to some useful macros, the unstable feature in stable Rust:
Just like Python, the
yield_! macro will interrupt the execution of the code block, the
gen.resume() function will return a
GeneratorState enum with the yielded value or the final return value.
If called with
yield_! macro will return
One last trick…
Every generators implement the trait
Generator<Yield = Y, Return = R>. If, like me, you have some Python background, you’d like to return such generators, possibly make a trait with a function to return such generators, the problem here is:
- you can’t use
impl Traitin type-aliases or in trait function signatures (unstable feature)
- you can’t return a local variable as a
&dyn Trait(the variable goes out of scope, this will never be a feature thankfully)
At the moment, one solution is to move the generator into a
You don’t need to wait to use this feature, genawaiter aims to be a “drop-in” replacement of the currently unstable feature. Once it’s generally available, it should be a matter of renaming imports.