Reduce the genericity of closures in the iterator traits
By default, closures inherit the generic parameters of their scope, including `Self`. However, in most cases, the closures used to implement iterators don't need to be generic on the iterator type, only its `Item` type. We can reduce this genericity by redirecting such closures through local functions. This does make the closures more cumbersome to write, but it will hopefully reduce duplication in their monomorphizations, as well as their related type lengths.
This commit is contained in:
parent
60960a260f
commit
e67620afc4
3 changed files with 194 additions and 80 deletions
|
@ -85,28 +85,28 @@ macro_rules! float_sum_product {
|
||||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||||
impl Sum for $a {
|
impl Sum for $a {
|
||||||
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
|
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||||
iter.fold(0.0, |a, b| a + b)
|
iter.fold(0.0, Add::add)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||||
impl Product for $a {
|
impl Product for $a {
|
||||||
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
|
||||||
iter.fold(1.0, |a, b| a * b)
|
iter.fold(1.0, Mul::mul)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||||
impl<'a> Sum<&'a $a> for $a {
|
impl<'a> Sum<&'a $a> for $a {
|
||||||
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||||
iter.fold(0.0, |a, b| a + *b)
|
iter.fold(0.0, Add::add)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||||
impl<'a> Product<&'a $a> for $a {
|
impl<'a> Product<&'a $a> for $a {
|
||||||
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
|
||||||
iter.fold(1.0, |a, b| a * *b)
|
iter.fold(1.0, Mul::mul)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
|
|
|
@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iter_rfold", since = "1.27.0")]
|
#[stable(feature = "iter_rfold", since = "1.27.0")]
|
||||||
fn rfold<B, F>(mut self, accum: B, mut f: F) -> B
|
fn rfold<B, F>(mut self, accum: B, f: F) -> B
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(B, Self::Item) -> B,
|
F: FnMut(B, Self::Item) -> B,
|
||||||
{
|
{
|
||||||
self.try_rfold(accum, 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_rfold(accum, ok(f)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Searches for an element of an iterator from the back that satisfies a predicate.
|
/// Searches for an element of an iterator from the back that satisfies a predicate.
|
||||||
|
@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iter_rfind", since = "1.27.0")]
|
#[stable(feature = "iter_rfind", since = "1.27.0")]
|
||||||
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
|
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
P: FnMut(&Self::Item) -> bool
|
P: FnMut(&Self::Item) -> bool
|
||||||
{
|
{
|
||||||
self.try_rfold((), move |(), x| {
|
#[inline]
|
||||||
if predicate(&x) { LoopState::Break(x) }
|
fn check<T>(
|
||||||
else { LoopState::Continue(()) }
|
mut predicate: impl FnMut(&T) -> bool,
|
||||||
}).break_value()
|
) -> impl FnMut((), T) -> LoopState<(), T> {
|
||||||
|
move |(), x| {
|
||||||
|
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.try_rfold((), check(predicate)).break_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,11 +234,16 @@ pub trait Iterator {
|
||||||
/// assert_eq!(a.iter().count(), 5);
|
/// assert_eq!(a.iter().count(), 5);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn count(self) -> usize where Self: Sized {
|
fn count(self) -> usize where Self: Sized {
|
||||||
// Might overflow.
|
// 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.
|
/// Consumes the iterator, returning the last element.
|
||||||
|
@ -596,10 +601,15 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iterator_for_each", since = "1.21.0")]
|
#[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: 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
|
/// Creates an iterator which uses a closure to determine if an element
|
||||||
|
@ -1490,21 +1500,30 @@ pub trait Iterator {
|
||||||
/// assert_eq!(odd, vec![1, 3]);
|
/// assert_eq!(odd, vec![1, 3]);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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,
|
Self: Sized,
|
||||||
B: Default + Extend<Self::Item>,
|
B: Default + Extend<Self::Item>,
|
||||||
F: FnMut(&Self::Item) -> bool
|
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 left: B = Default::default();
|
||||||
let mut right: B = Default::default();
|
let mut right: B = Default::default();
|
||||||
|
|
||||||
self.for_each(|x| {
|
self.for_each(extend(f, &mut left, &mut right));
|
||||||
if f(&x) {
|
|
||||||
left.extend(Some(x))
|
|
||||||
} else {
|
|
||||||
right.extend(Some(x))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
(left, right)
|
(left, right)
|
||||||
}
|
}
|
||||||
|
@ -1702,10 +1721,15 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
#[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: 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.
|
/// An iterator method that applies a function, producing a single, final value.
|
||||||
|
@ -1777,10 +1801,15 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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: 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.
|
/// Tests if every element of the iterator matches a predicate.
|
||||||
|
@ -1822,13 +1851,18 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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: Sized, F: FnMut(Self::Item) -> bool
|
||||||
{
|
{
|
||||||
self.try_for_each(move |x| {
|
#[inline]
|
||||||
if f(x) { LoopState::Continue(()) }
|
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
|
||||||
else { LoopState::Break(()) }
|
move |x| {
|
||||||
}) == LoopState::Continue(())
|
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.
|
/// Tests if any element of the iterator matches a predicate.
|
||||||
|
@ -1870,14 +1904,19 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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,
|
Self: Sized,
|
||||||
F: FnMut(Self::Item) -> bool
|
F: FnMut(Self::Item) -> bool
|
||||||
{
|
{
|
||||||
self.try_for_each(move |x| {
|
#[inline]
|
||||||
if f(x) { LoopState::Break(()) }
|
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
|
||||||
else { LoopState::Continue(()) }
|
move |x| {
|
||||||
}) == LoopState::Break(())
|
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.
|
/// Searches for an element of an iterator that satisfies a predicate.
|
||||||
|
@ -1924,14 +1963,19 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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,
|
Self: Sized,
|
||||||
P: FnMut(&Self::Item) -> bool,
|
P: FnMut(&Self::Item) -> bool,
|
||||||
{
|
{
|
||||||
self.try_for_each(move |x| {
|
#[inline]
|
||||||
if predicate(&x) { LoopState::Break(x) }
|
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> {
|
||||||
else { LoopState::Continue(()) }
|
move |x| {
|
||||||
}).break_value()
|
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
|
/// Applies function to the elements of iterator and returns
|
||||||
|
@ -1951,16 +1995,19 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iterator_find_map", since = "1.30.0")]
|
#[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,
|
Self: Sized,
|
||||||
F: FnMut(Self::Item) -> Option<B>,
|
F: FnMut(Self::Item) -> Option<B>,
|
||||||
{
|
{
|
||||||
self.try_for_each(move |x| {
|
#[inline]
|
||||||
match f(x) {
|
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),
|
Some(x) => LoopState::Break(x),
|
||||||
None => LoopState::Continue(()),
|
None => LoopState::Continue(()),
|
||||||
}
|
}
|
||||||
}).break_value()
|
}
|
||||||
|
|
||||||
|
self.try_for_each(check(f)).break_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Searches for an element in an iterator, returning its index.
|
/// Searches for an element in an iterator, returning its index.
|
||||||
|
@ -2018,17 +2065,24 @@ pub trait Iterator {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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,
|
Self: Sized,
|
||||||
P: FnMut(Self::Item) -> bool,
|
P: FnMut(Self::Item) -> bool,
|
||||||
{
|
{
|
||||||
// The addition might panic on overflow
|
// The addition might panic on overflow
|
||||||
self.try_fold(0, move |i, x| {
|
#[inline]
|
||||||
if predicate(x) { LoopState::Break(i) }
|
#[rustc_inherit_overflow_checks]
|
||||||
else { LoopState::Continue(i + 1) }
|
fn check<T>(
|
||||||
}).break_value()
|
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
|
/// Searches for an element in an iterator from the right, returning its
|
||||||
|
@ -2071,18 +2125,25 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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,
|
P: FnMut(Self::Item) -> bool,
|
||||||
Self: Sized + ExactSizeIterator + DoubleEndedIterator
|
Self: Sized + ExactSizeIterator + DoubleEndedIterator
|
||||||
{
|
{
|
||||||
// No need for an overflow check here, because `ExactSizeIterator`
|
// No need for an overflow check here, because `ExactSizeIterator`
|
||||||
// implies that the number of elements fits into a `usize`.
|
// 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();
|
let n = self.len();
|
||||||
self.try_rfold(n, move |i, x| {
|
self.try_rfold(n, check(predicate)).break_value()
|
||||||
let i = i - 1;
|
|
||||||
if predicate(x) { LoopState::Break(i) }
|
|
||||||
else { LoopState::Continue(i) }
|
|
||||||
}).break_value()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum element of an iterator.
|
/// Returns the maximum element of an iterator.
|
||||||
|
@ -2151,11 +2212,22 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
|
#[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,
|
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.
|
// 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
|
/// Returns the element that gives the maximum value with respect to the
|
||||||
|
@ -2174,11 +2246,16 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iter_max_by", since = "1.15.0")]
|
#[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,
|
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
|
||||||
{
|
{
|
||||||
// switch to y even if it is only equal, to preserve stability.
|
// 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
|
/// Returns the element that gives the minimum value from the
|
||||||
|
@ -2195,12 +2272,24 @@ pub trait Iterator {
|
||||||
/// let a = [-3_i32, 0, 1, 5, -10];
|
/// let a = [-3_i32, 0, 1, 5, -10];
|
||||||
/// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
|
/// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
|
#[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,
|
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.
|
// 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
|
/// Returns the element that gives the minimum value with respect to the
|
||||||
|
@ -2219,11 +2308,16 @@ pub trait Iterator {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "iter_min_by", since = "1.15.0")]
|
#[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,
|
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
|
||||||
{
|
{
|
||||||
// only switch to y if it is strictly smaller, to preserve stability.
|
// 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2284,13 +2378,20 @@ pub trait Iterator {
|
||||||
FromB: Default + Extend<B>,
|
FromB: Default + Extend<B>,
|
||||||
Self: Sized + Iterator<Item=(A, 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 ts: FromA = Default::default();
|
||||||
let mut us: FromB = Default::default();
|
let mut us: FromB = Default::default();
|
||||||
|
|
||||||
self.for_each(|(t, u)| {
|
self.for_each(extend(&mut ts, &mut us));
|
||||||
ts.extend(Some(t));
|
|
||||||
us.extend(Some(u));
|
|
||||||
});
|
|
||||||
|
|
||||||
(ts, us)
|
(ts, us)
|
||||||
}
|
}
|
||||||
|
@ -2617,7 +2718,7 @@ pub trait Iterator {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
Self::Item: PartialOrd,
|
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.
|
/// Checks if the elements of this iterator are sorted using the given comparator function.
|
||||||
|
@ -2639,11 +2740,9 @@ pub trait Iterator {
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(curr) = self.next() {
|
while let Some(curr) = self.next() {
|
||||||
if compare(&last, &curr)
|
match compare(&last, &curr) {
|
||||||
.map(|o| o == Ordering::Greater)
|
Some(Ordering::Greater) | None => return false,
|
||||||
.unwrap_or(true)
|
_ => {}
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
last = curr;
|
last = curr;
|
||||||
}
|
}
|
||||||
|
@ -2687,17 +2786,21 @@ pub trait Iterator {
|
||||||
/// commonalities of {max,min}{,_by}. In particular, this avoids
|
/// commonalities of {max,min}{,_by}. In particular, this avoids
|
||||||
/// having to implement optimizations several times.
|
/// having to implement optimizations several times.
|
||||||
#[inline]
|
#[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
|
where
|
||||||
I: Iterator,
|
I: Iterator,
|
||||||
F: FnMut(&I::Item, &I::Item) -> bool,
|
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
|
// start with the first element as our selection. This avoids
|
||||||
// having to use `Option`s inside the loop, translating to a
|
// having to use `Option`s inside the loop, translating to a
|
||||||
// sizeable performance gain (6x in one case).
|
// sizeable performance gain (6x in one case).
|
||||||
it.next().map(|first| {
|
let first = it.next()?;
|
||||||
it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel })
|
Some(it.fold(first, select(f)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
Loading…
Add table
Reference in a new issue