Skip to content

A Rust library to make writing generators straightforward.

License

Notifications You must be signed in to change notification settings

m7andrew/generators

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Generators

A Rust library to make writing generators straightforward. As with Python generators, the generator macro provides a nice way to write an iterator as a single function.

#[generator]
fn numbers() -> i32 {
  yield 1;
  yield 2;
  yield 3;
}

This library supports: try expressions ?, early returns, recursion, and the yield_from macro.

Installation

This library currently requires nightly Rust as it uses coroutine features not yet surfaced to stable Rust. To use in your project, add generators as a dependency to your Cargo.toml file:

[dependencies]
generators = { git = "https://github.com/m7andrew/generators" }

You will then need to add these feature flags to the top of your main.rs or lib.rs file:

#![feature(coroutines, coroutine_trait, try_trait_v2, lifetime_capture_rules_2024)]

Usage

Generators are created with the #[generator] macro. This takes a function and transforms it into a function that returns an iterator. Because generators create iterators, your generator functions must have explicit return types.

Recursive generators are possible via the boxed attribute: #[generator(boxed)]. This extra attribute is needed because in order for coroutines (like generators) to be recursive in Rust, they must be boxed and thus heap allocated.

Returns within a generator act as a final yield. A return will first yield its value and then end the generator on the next iteration (returning None). This is useful for early returns. An empty return will simply end the generator without first yielding something.

To yield from another generator or iterator, use the yield_from! macro. This is similar to Python's yield from.

For examples, please take a look at the tests.

Future Rust

While Rust generators have been in the works for years, they are far from completion. In the 2024 edition of Rust, gen blocks are partially implemented and may be usable... someday. Currently, try expressions don't work as laid out in the RFC and other design decisions have yet to be hammered out. So until then, this library aims to provide a nice way to use some of Rust's cutting-edge features.

Limitations

  1. As a macro, error messages will not be as nice as those coming from native language features. Sorry.

  2. Implicit returns, or final expression returns will throw a compile error. Besides the semantic ambiguity, there is no way (that I know of) for macros to detect implicit returns. So stick with yield and return when writing your generators.

  3. Async generators are currently not implemented due to the complexity it would add.