-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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 Peekable::until #75540
Add Peekable::until #75540
Conversation
Useful to parse since you can read from an iterator until a specific predicate becomes true, without consuming the positive item.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @joshtriplett (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. |
d1a0ac6
to
18b7e8a
Compare
cc @jyn514 |
Co-authored-by: Lonami <totufals@hotmail.com>
Co-authored-by: Lonami <totufals@hotmail.com>
@@ -1687,6 +1687,110 @@ impl<I: Iterator> Peekable<I> { | |||
{ | |||
self.next_if(|next| next == expected) | |||
} | |||
|
|||
/// Creates an iterator that consumes elements until predicate is | |||
/// true, without consuming the last matching element. |
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.
/// true, without consuming the last matching element. | |
/// true, without consuming the last, matching element. |
/// ``` | ||
/// [`skip_while`]: trait.Iterator.html#method.skip_while | ||
#[unstable(feature = "peekable_next_if", issue = "72480")] | ||
pub fn until<P: FnMut(&I::Item) -> bool>(&mut self, func: P) -> Until<'_, I, P> { |
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.
Shouldn't think be take_until
? We should also link take_while
here for a non-consuming version. This is what I am looking for.
peekable: &'a mut Peekable<I>, | ||
flag: bool, | ||
predicate: P, | ||
} |
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.
} | |
} | |
/// documentation for more. | ||
/// | ||
/// [`until`]: trait.Peekable.html#until | ||
/// [`Iterator`]: trait.Iterator.html |
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.
cross doc link, we probably don't need this. @jyn514 would be happy if you remove this
/// closure on each element of the iterator, and consume elements | ||
/// until it returns true. | ||
/// | ||
/// After true is returned, until()'s job is over, and the iterator |
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.
/// After true is returned, until()'s job is over, and the iterator | |
/// After `true` is returned, `until()`'s job is over, and the iterator |
I: Iterator, | ||
{ | ||
peekable: &'a mut Peekable<I>, | ||
flag: 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.
Can we remove flag? And use predicate: Option<P>
to indicate that it can still be iterated on?
type Item = I::Item; | ||
|
||
#[inline] | ||
fn next(&mut self) -> Option<I::Item> { |
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.
skip_while
uses fn check
most likely to optimized the assembly (size and cache), how does this assembly looks like? @lzutao do you think this will have an impact? SkipWhile
impl<I: Iterator, P> Iterator for SkipWhile<I, P>
where
P: FnMut(&I::Item) -> bool,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
fn check<'a, T>(
flag: &'a mut bool,
pred: &'a mut impl FnMut(&T) -> bool,
) -> impl FnMut(&T) -> bool + 'a {
move |x| {
if *flag || !pred(x) {
*flag = true;
true
} else {
false
}
}
}
let flag = &mut self.flag;
let pred = &mut self.predicate;
self.iter.find(check(flag, pred))
}
fn size_hint(&self) -> (usize, Option<usize>) { | ||
let (_, upper) = self.peekable.size_hint(); | ||
(0, upper) // can't know a lower bound, due to the predicate | ||
} |
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.
Shouldn't we override try_fold
and fold
too?
After working with iterators on fish-manpage-completions for quite a bit, I find this function lacking and we used the one from itertools In case someone use
I feel confused myself now too, or maybe this should be discussed more in But the solution is as simple as moving |
Yeah, I didn't know about |
Should this be closed? It sounds like @apelisse has lost interest and I don't know anyone else planning to use this API. |
I'm happy to close, feel free to re-open if needed. |
I do am interested in this since I need it but not that important to me to focus on this right now. It may create more footgun that I need to see into peeking. |
FWIW I'd be interested in doing whatever changes the libs team desires. The lack of an API like this threw me off when I ran into it, and took a big of debug prints to figure out what was happening. |
@jhpratt sure, feel free to make a new PR with the changes from this one |
Useful to parse since you can read from an iterator until a specific
predicate becomes true, without consuming the positive item.
Following up on #72310 (comment). I've also reused the same "issue", I know nothing about the process.