-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Add Iterator::map_while
#66577
Add Iterator::map_while
#66577
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @sfackler (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
That method name is a lot, but it does seem potentially useful? @rfcbot fcp merge |
Team member @sfackler has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns: 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. |
For the record, this was previously proposed in #65864. It was not merged because I (randomly assigned reviewer) and the two T-libs members who voiced an opinion after I pinged the team were lukewarm on adding it to std instead of itertools. Take from that what you will. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
If we want to add this I think |
src/libcore/iter/adapters/mod.rs
Outdated
} | ||
} | ||
|
||
#[unstable(feature = "iter_take_while_map", reason = "recently added", issue = "0")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stability attributes currently don't work with trait impls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why then there is a #[stable(feature = "rust1", since = "1.0.0")]
on Iterator
impl for TakeWhile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unstability attributes that don't work. ;) There is no such thing as an unstable trait impl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand :( You said that there is no unstable trait impl, but
- without
#[unsatble]
this code doesn't compile: - there are other
#[unstable]
impls, e.g.:impl TrustedLen for Rev
- there are
#[stable]
impls too, e.g.:impl Iterator for Rev
Ping from triage: |
@JohnCSimon this is still pending FCP waiting on @Kimundi, @KodrAus, @SimonSapin, @dtolnay, and @withoutboats. |
@rfcbot concern name My view: I don't have strong feelings either way about adding this API, if someone else on the libs team wants to drive it (seems like sfackler does) that's fine with me, but if we do add it this API I want it to be named |
+1 for calling this map_while. @rfcbot reviewed |
☔ The latest upstream changes (presumably #67485) made this pull request unmergeable. Please resolve the merge conflicts. |
☔ The latest upstream changes (presumably #67540) made this pull request unmergeable. Please resolve the merge conflicts. |
Heh, I'm not sure why my PR didn't gain the same traction this one does, but I'm glad it seems to be going somewhere. I actually almost submitted it as |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
☔ The latest upstream changes (presumably #67596) made this pull request unmergeable. Please resolve the merge conflicts. |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
#[derive(Clone)] | ||
pub struct MapWhile<I, P> { | ||
iter: I, | ||
finished: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the finished
field needed? It looks like it's only used to make MapWhile
fused but that seems unnecessary when you can instead just call .fuse()
if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole point of the MapWhile
is that it stops on first None
just like TakeWhile
stops on first false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It stops by having .next()
return None
. The finished
field isn't needed to do that. After then it doesn't matter what .next()
returns unless the iterator implements FusedIterator
which MapWhile
doesn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I first thought it was to improve the upper bound of size_hint
, but it also doesn't matter what that method returns once the iterator has been exhausted. So I suppose you're right. We probably can't remove it from TakeWhile
though, since it already implements FusedIterator
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be a bit confusing, so if we do remove finished
flag, then I think we need to mention it in the docs
☔ The latest upstream changes (presumably #68234) made this pull request unmergeable. Please resolve the merge conflicts. |
c88c3ef
to
db1a107
Compare
Rebased to resolve conflicts with master |
@Mark-Simulacrum Can you merge this pr? I've added the tracking issue to the |
@bors r=mark-simulcrum |
📌 Commit db1a107 has been approved by |
…=mark-simulcrum Add `Iterator::map_while` In `Iterator` trait there is `*_map` version of [`filter`] — [`filter_map`], however, there is no `*_map` version of [`take_while`], that can also be useful. ### Use cases In my code, I've found that I need to iterate through iterator of `Option`s, stopping on the first `None`. So I've written code like this: ```rust let arr = [Some(4), Some(10), None, Some(3)]; let mut iter = arr.iter() .take_while(|x| x.is_some()) .map(|x| x.unwrap()); assert_eq!(iter.next(), Some(4)); assert_eq!(iter.next(), Some(10)); assert_eq!(iter.next(), None); assert_eq!(iter.next(), None); ``` Thit code 1) isn't clean 2) In theory, can generate bad bytecode (I'm actually **not** sure, but I think that `unwrap` would generate additional branches with `panic!`) The same code, but with `map_while` (in the original PR message it was named "take_while_map"): ```rust let arr = [Some(4), Some(10), None, Some(3)]; let mut iter = arr.iter().map_while(std::convert::identity); ``` Also, `map_while` can be useful when converting something (as in [examples]). [`filter`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter [`filter_map`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map [`take_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.take_while [examples]: https://github.com/rust-lang/rust/compare/master...WaffleLapkin:iter_take_while_map?expand=1#diff-7e57917f962fe6ffdfba51e4955ad6acR1042
…crum Add `Iterator::map_while` In `Iterator` trait there is `*_map` version of [`filter`] — [`filter_map`], however, there is no `*_map` version of [`take_while`], that can also be useful. ### Use cases In my code, I've found that I need to iterate through iterator of `Option`s, stopping on the first `None`. So I've written code like this: ```rust let arr = [Some(4), Some(10), None, Some(3)]; let mut iter = arr.iter() .take_while(|x| x.is_some()) .map(|x| x.unwrap()); assert_eq!(iter.next(), Some(4)); assert_eq!(iter.next(), Some(10)); assert_eq!(iter.next(), None); assert_eq!(iter.next(), None); ``` Thit code 1) isn't clean 2) In theory, can generate bad bytecode (I'm actually **not** sure, but I think that `unwrap` would generate additional branches with `panic!`) The same code, but with `map_while` (in the original PR message it was named "take_while_map"): ```rust let arr = [Some(4), Some(10), None, Some(3)]; let mut iter = arr.iter().map_while(std::convert::identity); ``` Also, `map_while` can be useful when converting something (as in [examples]). [`filter`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter [`filter_map`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter_map [`take_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.take_while [examples]: https://github.com/rust-lang/rust/compare/master...WaffleLapkin:iter_take_while_map?expand=1#diff-7e57917f962fe6ffdfba51e4955ad6acR1042
☀️ Test successful - checks-azure |
…_while, r=LukasKalbertodt Remove `finished` flag from `MapWhile` This PR removes `finished` flag from `MapWhile` as been proposed in rust-lang#66577 (comment). This also resolves open questions of the tracking issue (rust-lang#68537): - `MapWhile` can't implement both + `DoubleEndedIterator` (discussed in rust-lang#66577 (comment) and following comments) + `FusedIterator` (this pr removes `finished` flag, so `MapWhile` isn't fused anymore) - Debug output (this pr removes `finished` flag, so there is no question in including it in debug output) r? @Mark-Simulacrum
In
Iterator
trait there is*_map
version offilter
—filter_map
, however, there is no*_map
version oftake_while
, that can also be useful.Use cases
In my code, I've found that I need to iterate through iterator of
Option
s, stopping on the firstNone
. So I've written code like this:Thit code
unwrap
would generate additional branches withpanic!
)The same code, but with
map_while
(in the original PR message it was named "take_while_map"):Also,
map_while
can be useful when converting something (as in examples).