-
Notifications
You must be signed in to change notification settings - Fork 310
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 take_while_inclusive
method
#616
Changes from all commits
11ca791
60d5c7c
37cd391
d67e86f
681ed7a
0b49d8b
91fe99e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
use core::iter::FusedIterator; | ||
use std::fmt; | ||
|
||
/// An iterator adaptor that consumes elements while the given predicate is | ||
/// `true`, including the element for which the predicate first returned | ||
/// `false`. | ||
/// | ||
/// See [`.take_while_inclusive()`](crate::Itertools::take_while_inclusive) | ||
/// for more information. | ||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] | ||
pub struct TakeWhileInclusive<'a, I: 'a, F> { | ||
iter: &'a mut I, | ||
predicate: F, | ||
done: bool, | ||
} | ||
|
||
impl<'a, I, F> TakeWhileInclusive<'a, I, F> | ||
where | ||
I: Iterator, | ||
F: FnMut(&I::Item) -> bool, | ||
{ | ||
/// Create a new [`TakeWhileInclusive`] from an iterator and a predicate. | ||
pub fn new(iter: &'a mut I, predicate: F) -> Self { | ||
Self { iter, predicate, done: false} | ||
} | ||
} | ||
|
||
impl<'a, I, F> fmt::Debug for TakeWhileInclusive<'a, I, F> | ||
where I: Iterator + fmt::Debug, | ||
{ | ||
debug_fmt_fields!(TakeWhileInclusive, iter); | ||
} | ||
|
||
impl<'a, I, F> Iterator for TakeWhileInclusive<'a, I, F> | ||
where | ||
I: Iterator, | ||
F: FnMut(&I::Item) -> bool | ||
{ | ||
type Item = I::Item; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pondering: Would it be worth returning the result of the predicate in some way in the item type, since that information is known free anyway? I was reminded of My brain then thought about things like Dunno if any of that is useful or worth doing, but I figured I'd toss it out for discussion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returning a custom type that Deref's to the actual item type but has additional information about the predicate could be a good idea. Otherwise, the call site might be able to infer it:
Given those rules, it might also be an idea to make that information accessible from the edit: nvm the proposal. The rule is correct but when instantiating the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I should have read the Iterator docs better. It looks like what I propose would be named I'll add that to the ACP, if one gets opened. |
||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
if self.done { | ||
None | ||
} else { | ||
self.iter.next().map(|item| { | ||
if !(self.predicate)(&item) { | ||
self.done = true; | ||
} | ||
item | ||
}) | ||
} | ||
} | ||
|
||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
if self.done { | ||
(0, Some(0)) | ||
} else { | ||
(0, self.iter.size_hint().1) | ||
} | ||
} | ||
} | ||
|
||
impl<I, F> FusedIterator for TakeWhileInclusive<'_, I, F> | ||
where | ||
I: Iterator, | ||
F: FnMut(&I::Item) -> 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.
As suggested in the original pull github issue in rust, wouldn't something like
take_until
be easier to find?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 think so. The motivation for this method is "
take_while
but keeping the last element".take_until
doesn't imply anything about the behavior with the final element—the only thing it implies is that the semantics of the predicate are reversed, e.g.:If I just read this code without reading any docs, I would probably assume these did the same thing, and certainly wouldn't guess the motivation of having both methods. The negation becomes the most noticeable difference and distracts from the actual purpose.
Plus, if I see
take_while
in std and I'm looking for a method that's almost that but lets me keep the last element, I'm much more likely to findtake_while_inclusive
thantake_until
. And I'd be annoyed to have to negate the predicate if I was converting one to the other.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'm definitely used to
until COND
being shorthand forwhile !COND
, like with https://www.perltutorial.org/perl-until/, not implying another iteration or similar.