/// assert_eq!(a.iter().count(), 5);
/// ```
#[inline]
- #[rustc_inherit_overflow_checks]
#[stable(feature = "rust1", since = "1.0.0")]
fn count(self) -> usize where Self: Sized {
// Might overflow.
- self.fold(0, |cnt, _| cnt + 1)
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ fn add1<T>(count: usize, _: T) -> usize {
+ count + 1
+ }
+
+ self.fold(0, add1)
}
/// Consumes the iterator, returning the last element.
/// ```
#[inline]
#[stable(feature = "iterator_for_each", since = "1.21.0")]
- fn for_each<F>(self, mut f: F) where
+ fn for_each<F>(self, f: F) where
Self: Sized, F: FnMut(Self::Item),
{
- self.fold((), move |(), item| f(item));
+ #[inline]
+ fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) {
+ move |(), item| f(item)
+ }
+
+ self.fold((), call(f));
}
/// Creates an iterator which uses a closure to determine if an element
/// assert_eq!(odd, vec![1, 3]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- fn partition<B, F>(self, mut f: F) -> (B, B) where
+ fn partition<B, F>(self, f: F) -> (B, B) where
Self: Sized,
B: Default + Extend<Self::Item>,
F: FnMut(&Self::Item) -> bool
{
+ #[inline]
+ fn extend<'a, T, B: Extend<T>>(
+ mut f: impl FnMut(&T) -> bool + 'a,
+ left: &'a mut B,
+ right: &'a mut B,
+ ) -> impl FnMut(T) + 'a {
+ move |x| {
+ if f(&x) {
+ left.extend(Some(x));
+ } else {
+ right.extend(Some(x));
+ }
+ }
+ }
+
let mut left: B = Default::default();
let mut right: B = Default::default();
- self.for_each(|x| {
- if f(&x) {
- left.extend(Some(x))
- } else {
- right.extend(Some(x))
- }
- });
+ self.for_each(extend(f, &mut left, &mut right));
(left, right)
}
/// ```
#[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
- fn try_for_each<F, R>(&mut self, mut f: F) -> R where
+ fn try_for_each<F, R>(&mut self, f: F) -> R where
Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()>
{
- self.try_fold((), move |(), x| f(x))
+ #[inline]
+ fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
+ move |(), x| f(x)
+ }
+
+ self.try_fold((), call(f))
}
/// An iterator method that applies a function, producing a single, final value.
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn fold<B, F>(mut self, init: B, mut f: F) -> B where
+ fn fold<B, F>(mut self, init: B, f: F) -> B where
Self: Sized, F: FnMut(B, Self::Item) -> B,
{
- self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
+ #[inline]
+ fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
+ move |acc, x| Ok(f(acc, x))
+ }
+
+ self.try_fold(init, ok(f)).unwrap()
}
/// Tests if every element of the iterator matches a predicate.
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn all<F>(&mut self, mut f: F) -> bool where
+ fn all<F>(&mut self, f: F) -> bool where
Self: Sized, F: FnMut(Self::Item) -> bool
{
- self.try_for_each(move |x| {
- if f(x) { LoopState::Continue(()) }
- else { LoopState::Break(()) }
- }) == LoopState::Continue(())
+ #[inline]
+ fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+ move |x| {
+ if f(x) { LoopState::Continue(()) }
+ else { LoopState::Break(()) }
+ }
+ }
+
+ self.try_for_each(check(f)) == LoopState::Continue(())
}
/// Tests if any element of the iterator matches a predicate.
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn any<F>(&mut self, mut f: F) -> bool where
+ fn any<F>(&mut self, f: F) -> bool where
Self: Sized,
F: FnMut(Self::Item) -> bool
{
- self.try_for_each(move |x| {
- if f(x) { LoopState::Break(()) }
- else { LoopState::Continue(()) }
- }) == LoopState::Break(())
+ #[inline]
+ fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+ move |x| {
+ if f(x) { LoopState::Break(()) }
+ else { LoopState::Continue(()) }
+ }
+ }
+
+ self.try_for_each(check(f)) == LoopState::Break(())
}
/// Searches for an element of an iterator that satisfies a predicate.
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
+ fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
{
- self.try_for_each(move |x| {
- if predicate(&x) { LoopState::Break(x) }
- else { LoopState::Continue(()) }
- }).break_value()
+ #[inline]
+ fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> {
+ move |x| {
+ if predicate(&x) { LoopState::Break(x) }
+ else { LoopState::Continue(()) }
+ }
+ }
+
+ self.try_for_each(check(predicate)).break_value()
}
/// Applies function to the elements of iterator and returns
/// ```
#[inline]
#[stable(feature = "iterator_find_map", since = "1.30.0")]
- fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
+ fn find_map<B, F>(&mut self, f: F) -> Option<B> where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
{
- self.try_for_each(move |x| {
- match f(x) {
+ #[inline]
+ fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> {
+ move |x| match f(x) {
Some(x) => LoopState::Break(x),
None => LoopState::Continue(()),
}
- }).break_value()
+ }
+
+ self.try_for_each(check(f)).break_value()
}
/// Searches for an element in an iterator, returning its index.
///
/// ```
#[inline]
- #[rustc_inherit_overflow_checks]
#[stable(feature = "rust1", since = "1.0.0")]
- fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
+ fn position<P>(&mut self, predicate: P) -> Option<usize> where
Self: Sized,
P: FnMut(Self::Item) -> bool,
{
// The addition might panic on overflow
- self.try_fold(0, move |i, x| {
- if predicate(x) { LoopState::Break(i) }
- else { LoopState::Continue(i + 1) }
- }).break_value()
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ fn check<T>(
+ mut predicate: impl FnMut(T) -> bool,
+ ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+ move |i, x| {
+ if predicate(x) { LoopState::Break(i) }
+ else { LoopState::Continue(i + 1) }
+ }
+ }
+
+ self.try_fold(0, check(predicate)).break_value()
}
/// Searches for an element in an iterator from the right, returning its
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
+ fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
P: FnMut(Self::Item) -> bool,
Self: Sized + ExactSizeIterator + DoubleEndedIterator
{
// No need for an overflow check here, because `ExactSizeIterator`
// implies that the number of elements fits into a `usize`.
+ #[inline]
+ fn check<T>(
+ mut predicate: impl FnMut(T) -> bool,
+ ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+ move |i, x| {
+ let i = i - 1;
+ if predicate(x) { LoopState::Break(i) }
+ else { LoopState::Continue(i) }
+ }
+ }
+
let n = self.len();
- self.try_rfold(n, move |i, x| {
- let i = i - 1;
- if predicate(x) { LoopState::Break(i) }
- else { LoopState::Continue(i) }
- }).break_value()
+ self.try_rfold(n, check(predicate)).break_value()
}
/// Returns the maximum element of an iterator.
/// ```
#[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
- fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+ fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item) -> B,
{
+ #[inline]
+ fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+ move |x| (f(&x), x)
+ }
+
// switch to y even if it is only equal, to preserve stability.
- select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x)
+ #[inline]
+ fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+ x_p <= y_p
+ }
+
+ let (_, x) = select_fold1(self.map(key(f)), select)?;
+ Some(x)
}
/// Returns the element that gives the maximum value with respect to the
/// ```
#[inline]
#[stable(feature = "iter_max_by", since = "1.15.0")]
- fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
+ fn max_by<F>(self, compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
// switch to y even if it is only equal, to preserve stability.
- select_fold1(self, |x, y| compare(x, y) != Ordering::Greater)
+ #[inline]
+ fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+ move |x, y| compare(x, y) != Ordering::Greater
+ }
+
+ select_fold1(self, select(compare))
}
/// Returns the element that gives the minimum value from the
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
/// ```
+ #[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
- fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+ fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item) -> B,
{
+ #[inline]
+ fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+ move |x| (f(&x), x)
+ }
+
// only switch to y if it is strictly smaller, to preserve stability.
- select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x)
+ #[inline]
+ fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+ x_p > y_p
+ }
+
+ let (_, x) = select_fold1(self.map(key(f)), select)?;
+ Some(x)
}
/// Returns the element that gives the minimum value with respect to the
/// ```
#[inline]
#[stable(feature = "iter_min_by", since = "1.15.0")]
- fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
+ fn min_by<F>(self, compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
// only switch to y if it is strictly smaller, to preserve stability.
- select_fold1(self, |x, y| compare(x, y) == Ordering::Greater)
+ #[inline]
+ fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+ move |x, y| compare(x, y) == Ordering::Greater
+ }
+
+ select_fold1(self, select(compare))
}
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item=(A, B)>,
{
+ fn extend<'a, A, B>(
+ ts: &'a mut impl Extend<A>,
+ us: &'a mut impl Extend<B>,
+ ) -> impl FnMut((A, B)) + 'a {
+ move |(t, u)| {
+ ts.extend(Some(t));
+ us.extend(Some(u));
+ }
+ }
+
let mut ts: FromA = Default::default();
let mut us: FromB = Default::default();
- self.for_each(|(t, u)| {
- ts.extend(Some(t));
- us.extend(Some(u));
- });
+ self.for_each(extend(&mut ts, &mut us));
(ts, us)
}
Self: Sized,
Self::Item: PartialOrd,
{
- self.is_sorted_by(|a, b| a.partial_cmp(b))
+ self.is_sorted_by(PartialOrd::partial_cmp)
}
/// Checks if the elements of this iterator are sorted using the given comparator function.
};
while let Some(curr) = self.next() {
- if compare(&last, &curr)
- .map(|o| o == Ordering::Greater)
- .unwrap_or(true)
- {
- return false;
+ match compare(&last, &curr) {
+ Some(Ordering::Greater) | None => return false,
+ _ => {}
}
last = curr;
}
/// commonalities of {max,min}{,_by}. In particular, this avoids
/// having to implement optimizations several times.
#[inline]
-fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item>
+fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
where
I: Iterator,
F: FnMut(&I::Item, &I::Item) -> bool,
{
+ #[inline]
+ fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T {
+ move |sel, x| if f(&sel, &x) { x } else { sel }
+ }
+
// start with the first element as our selection. This avoids
// having to use `Option`s inside the loop, translating to a
// sizeable performance gain (6x in one case).
- it.next().map(|first| {
- it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel })
- })
+ let first = it.next()?;
+ Some(it.fold(first, select(f)))
}
#[stable(feature = "rust1", since = "1.0.0")]