Do not wait for Rust generators

David Delassus
2 min readMay 11, 2022

--

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:

The yield keyword interrupts the function and produce the supplied value. Now, instead of using the next() function to resume the generator, you can use:

  • gen.send(value): the yield keyword will return value when resuming
  • gen.throw(exc): the yield keyword will throw exc when resuming
  • gen.close(): the generator won’t resume (and raise a StopIteration)

NB: This is also called a coroutine.

They are a powerful tool. In fact, they were used for concurrency before the rise of async/await!

Unfortunately, at the time of writing, this is still an unstable feature in Rust.

Introducing… genawaiter!

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 gen.resume_with(arg), the yield_! macro will return arg.

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 Trait in 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 Box<dyn Trait>:

Conclusion

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.

--

--

David Delassus
David Delassus

Written by David Delassus

CEO & Co-Founder at Link Society

Responses (2)