Are you familiar with `core::other::from_fn`[1]. This allows converting from `impl FnMut() -> Option<T>` to `impl Iterator<Item = T>`.
I recognise that these aren't strictly generators - you need to do your own state tracking. However, this does make it easier to do that ad-hoc.
I believe there is some work in the ecosystem abusing `async` to make fake generators, although I haven't used any of them.
[1]: https://doc.rust-lang.org/stable/core/iter/fn.from_fn.html
Re:A personal list of Rust grievances
by cropcirclbureau on Tuesday September 13, 2022 @06:51AM
(#32822653)
> `async` to make fake generators.
Genawaiter[0] is one of them.
Re:A personal list of Rust grievances
by estebank on Tuesday September 13, 2022 @10:59AM
(#32825147)
There's also an effort to get generators into the stable language, but it is currently gated on multiple open questions on the async iteration story, including what traits are to be involved (will it be `trait AsyncIteratorItem`? will it wait until GATs and/or async fn in traits and "keyword generics"/"maybe async" functions?), but you can see some explorations of the syntax aspect at https://github.com/estebank/iterator_item/
The proc-macro is written in such a way that it tries to parse as much as possible, so that you can try things out mixing and matching from the different alternatives that I've thought of: https://github.com/estebank/iterator_item/tree/master/tests
Like for example:
fn foo() => i32 {
for n in 0..10 {
yield n;
}
}
fn* foo() -> i32 {
for n in 0..10 {
yield n;
}
}
gen foo() -> i32 {
for n in 0..10 {
yield n;
}
}
fn* foo() yield i32 {
for n in 0..10 {
yield n;
}
}
One thing I love about these is how trivially easy it is to turn an Iterator<Item = Future<Output = T>> into an AsyncIterator<Item = T>: https://github.com/estebank/iterator_item/blob/b79d7b496687b... async fn* into_stream(input: impl Iterator<Item = Interval>)
yields Interval
{
for i in input {
yield i;
}
}
Re:A personal list of Rust grievances
by heavyset_go on Tuesday September 13, 2022 @04:24PM
(#32829743)
I'm aware of it, I just find it awkward for some tasks that would be easily expressed using generators in Python or JavaScript.
Python and JavaScript make it dead simple to create iterators using generator functions, and in Python's case, generator expressions, as well.
For example, there are a lot of problems that are solved simply and efficiency by chaining generators together in pipelines. That's a task that's easy to tackle in Python and even JavaScript, but it can sometimes be awkward with Rust when defining iterators in the first place.
It's frustrating because Rust has a lot of features that make working with iterators nice. It's just a shame that they're awkward to create from scratch.