adds async stream rfc by nellshamrell · Pull Request #2996 · rust-lang/rfcs · Gi...
source link: https://github.com/rust-lang/rfcs/pull/2996
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Contributor
nikomatsakis commented on Oct 1
We discussed this amongst the lang team at some point and concluded that this does not require @rust-lang/lang signoff. I've tagged it for @rust-lang/libs.
Member
joshtriplett commented on Oct 1
to adding try_next()
if possible.
Also: could we please standardize a method for converting from Iterator to Stream? That may not be able to use IntoStream (because a blanket impl for Iterator would conflict with more specific impls people may want to write), but having a function that takes an impl Iterator<Item = T>
and returns an impl Stream<Item = T>
would be really helpful.
to adding
try_next()
if possible.
@joshtriplett The conversation around whether to add Stream::next
took quite a while to resolve, and was only added because poll_next
by itself is not useful for end-users. The proposed try_next
adapter has no counterpart in Iterator
, is a minor helper to avoid writing .transpose()
, and doesn't include functionality unique to async Rust. I would prefer if the scope of this PR would not be expanded beyond what's already been proposed so we don't need to find consensus on the design of further stream adapters in order to stabilize Stream
.
Also: could we please standardize a method for converting from Iterator to Stream?
@joshtriplett async-std
has stream::from_iter
and futures-rs has stream::iter
. I don't know if you think this should be mentioned in the RFC, but adding a function with this functionality would be straightforward once we expose Stream
.
Member
joshtriplett commented on Oct 2
@yoshuawuyts To clarify, neither of those comments was intended as a blocker to this RFC. I think it makes sense to add a minimal implementation of Stream
, and after doing so, add additional helper functions like these to make it easier to work with.
Author
nellshamrell commented on Oct 2
Information about converting an iterator to a stream has been added :)
I finally got around to reading, this looks pretty good, I think including next is +1. I would really really like to see try_next
, I think this is by far the most useful fn I have used for streams. I don't really understand the reason to not include it? I don't think there is much consensus needed for it, we've already agreed how to do next
and try_next
shouldn't be much more complicated as far as I can tell.
Another example of !Unpin
streams are done via async-stream
crate https://github.com/tokio-rs/async-stream/ which is usable on stable today.
Thanks a ton @nellshamrell and other for pushing this through
I'm not sure where to comment on this, but given that this RFC discusses LendStream
, as a generalization, in theory at least there is a further generalization involving different lifetimes for the Lender, and the Item
, with a lifetime bounds that 'lender: 'item
. Which probably requires additional control mechanisms to regain ownership in the Lender.
With the idea that the single liftime LendingStream
is a specialization of it where the lifetimes are the same.
I haven't thought enough about the extent to which the further generalization can be expressed currently though.
It seemed since the discussion of LendingStream
as a generalization of Stream
up it might/might not be worth thinking about this further generalization
l4l left a comment
Just some minor typos, please check it out, I'm not a native speaker there might be mistakes.
That's an amazing job by the way, really like reading the rfc. Hope it would be approved soon.
Member
yoshuawuyts commented on Oct 13
I would really really like to see
try_next
[...] I don't really understand the reason to not include it?
@LucioFranco I covered that earlier in the thread #2996 (comment):
The proposed
try_next
adapter has no counterpart in Iterator, is a minor helper to avoid writing.transpose()
, and doesn't include functionality unique to async Rust. I would prefer if the scope of this PR would not be expanded beyond what's already been proposed so we don't need to find consensus on the design of further stream adapters in order to stabilizeStream
.
I see try_next
as being desirable only as long as we don't have async iteration syntax, and will fall out of fashion the moment we do. I know you'll see this differently, and discussing the scope and priorities of stream adapters will make for an interesting conversation. But do you really want to push us to find consensus on that now?
We're both part of the Async Foundations WG, and we've had the privilege of being able to set the direction of this RFC. And that was a success; we have consensus on everything included here! I think now is the time to ensure what's in this RFC is accurate, but not seek to expand its scope with subjects we then newly need to find consensus on.
Contributor
nikomatsakis commented on Oct 13
To ensure I understand, the role of try_next
is to allow you to write code like this?
while let Some(foo) = stream.try_next().await? { }
as opposed to this?
while let Some(foo) = stream.try_next().await { let foo = foo?; }
Hmm, I'm torn. I agree with @yoshuawuyts that we should avoid increasing the scope of the RFC in general, which is intentionally targeted. But I also think that the point of including next
was that it was something people would "immediately want" in practice, and I can imagine that try_next
also fits in that bucket. I'm not sure how important it is that it would become less useful if/when async iteration syntax is added, given that we don't have a clear timeline on that. Is the primary objection that the method will not be as useful in the future or are there other concerns?
I would want to hold the line against other forms of "scope creep", the only reason I can see to consider try_next
is that it feels very analogous to next
.
Contributor
nikomatsakis commented on Oct 13
Thinking on it more, I think what I'd prefer is to leave the RFC unaltered, land it, and consider try_next
separately as a PR. It feels like a fairly standard "libs addition". The only difference is that, if we plan to make the futures crate redirect to core, before we actually do that we will need to have a clear idea of what methods we have, because any additional methods will have to be carefully coordinated.
Member
LucioFranco commented on Oct 13
@yoshuawuyts sure, I am pretty sure I voiced my opinion during that period. It's also my fault for not pushing it harder, I got busy and that happens. I still don't follow your argument you referenced with iterators. I think Streams are not 1:1 with iterators but I rest my case.
@nikomatsakis right, I think most streams I have worked with return some sort of result so avoiding the first example in favor of the second is much nicer.
I think its fine to punt on this for now, just knowing that I think this is extremely useful. My question then is, what does that path look like to add try_next
and what does that look like in conjunction with the futures
crate? For example, I want to use this try_next
and when/if we add it to std will it just replace the one on the futures crate? To me I see this method as one of the foundational ones for this trait and I think that path needs to be clear.
The alternative to try_next
is
while let Some(foo) = stream.next().await.transpose()? { }
which is a pattern I've started using with fallible iterators as well, having to use a while let
instead of a for
loop is less annoying than having the let foo = foo?;
line inside the loop.
Contributor
tmandry commented 18 days ago
Just posted the last of my comments, I'm actually done now I promise :)
Author
nellshamrell commented 12 days ago
Addressed all of @tmandry's comments!
Contributor
tmandry left a comment
In light of #2996 (comment) that wording change should be reverted.
Otherwise, looks good!
Outdated
A user could create a stream as follows (Example taken from @yoshuawuyt's [implementation pull request](https://github.com/rust-lang/rust/pull/79023)).
Creating a stream involves two steps: creating a `struct` to
hold the stream's state, and then implementing [`Stream`] for that
Author
nellshamrell commented 5 days ago
@tmandry comments have been addressed!
Contributor
tmandry commented 3 days ago
I think this is ready for FCP. What do you think, @rust-lang/libs?
Member
sfackler commented 2 days ago
@rfcbot fcp merge
rfcbot commented 2 days ago •
Team member @sfackler has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK