I have a couple of comments.
In design requirements, the last 3 are dubious.
- Having streams work with
for
-loops (or someawait for
variant which I propose im my RFC) would be nice, but shouldn't be a requirement. Using both iterators and streams with regularfor
looks could be problematic since it need to suspend, but only in the stream case. Since there would be references which can't cross a suspend point, requiring a suspend point for looping over iterator would be quite restrictive. - Iterators can already be used with
for
-loops. You probably meant that generators can be iterators here? - I don't think we should restrict ourself to designs with interact well with
futures-rs
. It was not designed with generators in mind, but rather convenient asynchronous programming given the current feature set of Rust. We will probably end up with a design which works well with it, but having it be a requirement seems wrong.
futures-rs
combines return types and errors. This results in additional complexity when considering its traits when discussing generators. It is a good idea to deal with futures and streams which cannot results in errors. We can instead use Result
to indicate that a future or stream can result in an error. This is what I did in my RFC.
I don't think the R yield Y
sugar is a good idea, since you'd typically want to return iterators, futures or streams instead of plain generator types.
There are 2 reasons to have a Wait
or Blocked
variant on the result enum. You'd want yield x
to work in streams without having to write yield State::Yield(x)
there. This can be worked around with a yield!
macro, with some loss of ergonomics. The other is to allow await for
or for
-loops to iterate over streams. The loops needs to yield Wait
only when the streams it's waiting on does, so we need that concept in the language. This can again be worked around with a await_for!
macros with greater loss of ergonomics.
Note that an await
feature would not require the Wait
variant as part of the language. In a poll model, await
does the same thing as yield from
. These are also the same in Python (ignoring some dynamic type checks).
You do mention generators which do not start out paused. These are useful where the generators are consuming input. They also work for futures-rs
since it allows computations to start out immediately and well as starting out paused. I think this kind of generators will have to be separate kind of generators in the language, in addition to generators which start out paused. They do not work for iterators, and they aren't as nice for asynchronous programming since you have to pass around references to the event loop (like how you pass around Handle
in tokio
).
impl Iterator<Item=usize> + Move
doesn't actually work since built in traits leak through. We'll probably need some syntax to indicate that a generator is immovable (or movable).