Auto merge of #68820 - WaffleLapkin:remove_finished_from_map_while, r=LukasKalbertodt
Remove `finished` flag from `MapWhile` This PR removes `finished` flag from `MapWhile` as been proposed in https://github.com/rust-lang/rust/pull/66577#discussion_r370958025. This also resolves open questions of the tracking issue (#68537): - `MapWhile` can't implement both + `DoubleEndedIterator` (discussed in https://github.com/rust-lang/rust/pull/66577#discussion_r370947990 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
This commit is contained in:
commit
5ae85f43f4
2 changed files with 32 additions and 57 deletions
|
|
@ -1768,6 +1768,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I, P> FusedIterator for TakeWhile<I, P>
|
||||
where
|
||||
I: FusedIterator,
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
}
|
||||
|
||||
/// An iterator that only accepts elements while `predicate` returns `Some(_)`.
|
||||
///
|
||||
/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
|
||||
|
|
@ -1780,20 +1788,19 @@ where
|
|||
#[derive(Clone)]
|
||||
pub struct MapWhile<I, P> {
|
||||
iter: I,
|
||||
finished: bool,
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
impl<I, P> MapWhile<I, P> {
|
||||
pub(super) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
|
||||
MapWhile { iter, finished: false, predicate }
|
||||
MapWhile { iter, predicate }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MapWhile").field("iter", &self.iter).field("flag", &self.finished).finish()
|
||||
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1806,65 +1813,32 @@ where
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
if self.finished {
|
||||
None
|
||||
} else {
|
||||
let x = self.iter.next()?;
|
||||
let ret = (self.predicate)(x);
|
||||
self.finished = ret.is_none();
|
||||
ret
|
||||
}
|
||||
let x = self.iter.next()?;
|
||||
(self.predicate)(x)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.finished {
|
||||
(0, Some(0))
|
||||
} else {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
fn check<'a, B, T, Acc, R: Try<Ok = Acc>>(
|
||||
flag: &'a mut bool,
|
||||
p: &'a mut impl FnMut(T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
|
||||
move |acc, x| match p(x) {
|
||||
Some(item) => LoopState::from_try(fold(acc, item)),
|
||||
None => {
|
||||
*flag = true;
|
||||
LoopState::Break(Try::from_ok(acc))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.finished {
|
||||
Try::from_ok(init)
|
||||
} else {
|
||||
let flag = &mut self.finished;
|
||||
let p = &mut self.predicate;
|
||||
self.iter.try_fold(init, check(flag, p, fold)).into_try()
|
||||
}
|
||||
let Self { iter, predicate } = self;
|
||||
iter.try_fold(init, |acc, x| match predicate(x) {
|
||||
Some(item) => LoopState::from_try(fold(acc, item)),
|
||||
None => LoopState::Break(Try::from_ok(acc)),
|
||||
})
|
||||
.into_try()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I, P> FusedIterator for TakeWhile<I, P>
|
||||
where
|
||||
I: FusedIterator,
|
||||
P: FnMut(&I::Item) -> bool,
|
||||
{
|
||||
}
|
||||
|
||||
/// An iterator that skips over `n` elements of `iter`.
|
||||
///
|
||||
/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
|
||||
|
|
|
|||
|
|
@ -1037,9 +1037,6 @@ pub trait Iterator {
|
|||
/// closure on each element of the iterator, and yield elements
|
||||
/// while it returns [`Some(_)`][`Some`].
|
||||
///
|
||||
/// After [`None`] is returned, `map_while()`'s job is over, and the
|
||||
/// rest of the elements are ignored.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
|
@ -1079,15 +1076,14 @@ pub trait Iterator {
|
|||
/// #![feature(iter_map_while)]
|
||||
/// use std::convert::TryFrom;
|
||||
///
|
||||
/// let a = [0, -1, 1, -2];
|
||||
/// let a = [0, 1, 2, -3, 4, 5, -6];
|
||||
///
|
||||
/// let mut iter = a.iter().map_while(|x| u32::try_from(*x).ok());
|
||||
/// let iter = a.iter().map_while(|x| u32::try_from(*x).ok());
|
||||
/// let vec = iter.collect::<Vec<_>>();
|
||||
///
|
||||
/// assert_eq!(iter.next(), Some(0u32));
|
||||
///
|
||||
/// // We have more elements that are fit in u32, but since we already
|
||||
/// // got a None, map_while() isn't used any more
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3`
|
||||
/// // (as the `predicate` returned `None`) and `collect` stops at the first `None` entcountered.
|
||||
/// assert_eq!(vec, vec![0, 1, 2]);
|
||||
/// ```
|
||||
///
|
||||
/// Because `map_while()` needs to look at the value in order to see if it
|
||||
|
|
@ -1115,8 +1111,13 @@ pub trait Iterator {
|
|||
/// The `-3` is no longer there, because it was consumed in order to see if
|
||||
/// the iteration should stop, but wasn't placed back into the iterator.
|
||||
///
|
||||
/// Note that unlike [`take_while`] this iterator is **not** fused.
|
||||
/// It is also not specified what this iterator returns after the first` None` is returned.
|
||||
/// If you need fused iterator, use [`fuse`].
|
||||
///
|
||||
/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
/// [`fuse`]: #method.fuse
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue