-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
yield
without value from a gen
block
#123614
Comments
I'm not certain why it would make sense to do anything other than Given that the iterators returned by gen blocks are fused (#122829), it wouldn't make much sense to yield We could perhaps "reserve" the behavior by making it error, but seems unnecessarily cautious imo. |
Arguments for and against each option: Reject it entirelyPros:
Cons:
Return
|
The compiler could detect the presence of a bare |
That's a lot of subtlety (and complexity) for a really niche use case, imo, and I think that the user should just use |
At least for my one use-case today that motivated me to open this issue, that would have been an ergonomic hit. The use case: I am consuming an API that give me a stream of data. Sometimes there is new data available, sometimes there isn't yet (but might be in the future). My iterator returns loop {
for new_data in &mut iter {
process_data(new_data);
}
do_something_else_for_a_while();
} The above example could be easily converted to use let mut all_the_data = vec![];
loop {
all_the_data.extend(&mut iter);
do_something_else_for_a_while();
} |
I think code that tries to be clever should be explicit. And using an unfused iterator to only collect up to the first The behavior was not specified in the RFC, because it seemed obvious to me that we want to be consistent with I'm closing this issue as I don't see T-lang accepting
|
Out of curiosity, what would be your preferred "non-clever" version? An iterator over |
A function that explicitly turns an unfused iterator into an iterator of iterators so you can just write two nested for loops. |
That has a lot of hidden complexity. Consider the following: let mut iterator_of_iterators = unfused_iterator.oli_adapter();
// We never actually iterate over this.
// Does the `Drop` impl advance the inner
// unfused iterator until the next `None`?
// Or does it do nothing,
// and leave the elements we failed to iterate over
// to the `for` loop below?
let _ = iterator_of_iterators.next();
for item in iterator_of_iterators.next().unwrap() {
// ...
} |
Then maybe just handrolling the while let is actually the best way that does not hide any of the unclear things. |
You mean, handwrite duplicate implementations of |
I don't know what you mean, and issue format discussions are not a great place to discuss hypotheticals. Also, Aadding special cases to gen blocks won't help you, it just shifts the work to the language/libcore, where we then are unable to make breaking changes. If you have super special requirements, please write a dedicated crate for it, so others can reuse it and upstream optimizations to it. |
I am asking what you mean when you say "handrolling the while let". I'm not making any proposals—the proposal I did make was rejected, I want to understand your point of view on why you rejected it before I go around making new proposals. |
I presumed #123614 (comment) works for you and you just want a more concise version. If you want to make a proposal, I would recommend writing a crate that does the job for you and then explaining why there are limitations that are only solved by language or standard library support |
#123614 (comment) is how I use the un-fused iterator. I don't need or want a more concise version of that sort of code, existing language and stdlib affordances meet my needs just fine. What I want is to be able to use |
I don't think we're gonna go out of our way to support unfused iterators. There's no explicit support for them in the standard library functions for them beyond the fact of being sound even in their presence. An iterator is done when it returns We don't have async blocks that you can poll again after returning a value, even though the Future trait allows for it. |
(I agree that GitHub is not the best platform for this discussion, which is why I opened a thread on URLO; feel free to lock this issue) |
I tried this code:
I expected to see this happen: The gen blocks RFC does not specify the behavior of bare
yield
(without an argument). There are three possible choices, each with good reasons for and against:None
fromIterator::next()
yield ()
Instead, this happened: The current behavior is that of
yield ()
.Meta
rustc --version
:cc #117078
@rustbot label F-gen_blocks
The text was updated successfully, but these errors were encountered: