Rollup merge of #65222 - Lucretiel:fold_self, r=kodrAus
Proposal: `fold_self` and `try_fold_self` for Iterators This pull request proposes & implements two new methods on Iterators: `fold_self` and `try_fold_self`. These are variants of `fold` and `try_fold` that use the first element in the iterator as the initial accumulator. Let me know if a public feature like this requires an RFC, or if this pull request is sufficient as place for discussion.
This commit is contained in:
commit
87fdf35572
1 changed files with 39 additions and 16 deletions
|
|
@ -2005,6 +2005,43 @@ pub trait Iterator {
|
|||
self.try_fold(init, ok(f)).unwrap()
|
||||
}
|
||||
|
||||
/// The same as [`fold()`](#method.fold), but uses the first element in the
|
||||
/// iterator as the initial value, folding every subsequent element into it.
|
||||
/// If the iterator is empty, return `None`; otherwise, return the result
|
||||
/// of the fold.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Find the maximum value:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iterator_fold_self)]
|
||||
///
|
||||
/// fn find_max<I>(iter: I) -> Option<I::Item>
|
||||
/// where I: Iterator,
|
||||
/// I::Item: Ord,
|
||||
/// {
|
||||
/// iter.fold_first(|a, b| {
|
||||
/// if a >= b { a } else { b }
|
||||
/// })
|
||||
/// }
|
||||
/// let a = [10, 20, 5, -23, 0];
|
||||
/// let b: [u32; 0] = [];
|
||||
///
|
||||
/// assert_eq!(find_max(a.iter()), Some(&20));
|
||||
/// assert_eq!(find_max(b.iter()), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iterator_fold_self", issue = "68125")]
|
||||
fn fold_first<F>(mut self, f: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Self::Item, Self::Item) -> Self::Item,
|
||||
{
|
||||
let first = self.next()?;
|
||||
Some(self.fold(first, f))
|
||||
}
|
||||
|
||||
/// Tests if every element of the iterator matches a predicate.
|
||||
///
|
||||
/// `all()` takes a closure that returns `true` or `false`. It applies
|
||||
|
|
@ -2497,7 +2534,7 @@ pub trait Iterator {
|
|||
move |x, y| cmp::max_by(x, y, &mut compare)
|
||||
}
|
||||
|
||||
fold1(self, fold(compare))
|
||||
self.fold_first(fold(compare))
|
||||
}
|
||||
|
||||
/// Returns the element that gives the minimum value from the
|
||||
|
|
@ -2561,7 +2598,7 @@ pub trait Iterator {
|
|||
move |x, y| cmp::min_by(x, y, &mut compare)
|
||||
}
|
||||
|
||||
fold1(self, fold(compare))
|
||||
self.fold_first(fold(compare))
|
||||
}
|
||||
|
||||
/// Reverses an iterator's direction.
|
||||
|
|
@ -3214,20 +3251,6 @@ pub trait Iterator {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fold an iterator without having to provide an initial value.
|
||||
#[inline]
|
||||
fn fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
|
||||
where
|
||||
I: Iterator,
|
||||
F: FnMut(I::Item, I::Item) -> I::Item,
|
||||
{
|
||||
// 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).
|
||||
let first = it.next()?;
|
||||
Some(it.fold(first, f))
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator + ?Sized> Iterator for &mut I {
|
||||
type Item = I::Item;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue