Skip to content

Commit 9b429fd

Browse files
Lucretieltimvermeulen
authored andcommitted
Add fold_self
- Added `Iterator::fold_first`, which is like `fold`, but uses the first element in the iterator as the initial accumulator - Includes doc and doctest - Rebase commit; see #65222 for details Co-Authored-By: Tim Vermeulen <[email protected]>
1 parent 2fbb075 commit 9b429fd

File tree

1 file changed

+40
-16
lines changed

1 file changed

+40
-16
lines changed

src/libcore/iter/traits/iterator.rs

+40-16
Original file line numberDiff line numberDiff line change
@@ -2005,6 +2005,44 @@ pub trait Iterator {
20052005
self.try_fold(init, ok(f)).unwrap()
20062006
}
20072007

2008+
/// The same as [`fold()`](#method.fold), but uses the first element in the
2009+
/// iterator as the initial value, folding every subsequent element into it.
2010+
/// If the iterator is empty, return `None`; otherwise, return the result
2011+
/// of the fold.
2012+
///
2013+
/// # Example
2014+
///
2015+
/// Find the maximum value:
2016+
///
2017+
/// ```
2018+
/// fn find_max<I>(iter: I) -> Option<I::Item>
2019+
/// where I: Iterator,
2020+
/// I::Item: Ord,
2021+
/// {
2022+
/// iter.fold_first(|a, b| {
2023+
/// a.partial_cmp(b).map(move |cmp| match cmp {
2024+
/// Ordering::Greater | Ordering::Equal => a,
2025+
/// Ordering::Less => b,
2026+
/// })
2027+
/// })
2028+
/// }
2029+
/// let a = [10, 20, 5, -23, 0];
2030+
/// let b = [];
2031+
///
2032+
/// assert_eq!(find_max(a.iter()), Some(20));
2033+
/// assert_eq!(find_max(b.iter()), None);
2034+
/// ```
2035+
#[inline]
2036+
#[unstable(feature = "iterator_fold_self", issue = "68125")]
2037+
fn fold_first<F>(mut self, f: F) -> Option<Self::Item>
2038+
where
2039+
Self: Sized,
2040+
F: FnMut(Self::Item, Self::Item) -> Self::Item,
2041+
{
2042+
let first = self.next()?;
2043+
Some(self.fold(first, f))
2044+
}
2045+
20082046
/// Tests if every element of the iterator matches a predicate.
20092047
///
20102048
/// `all()` takes a closure that returns `true` or `false`. It applies
@@ -2497,7 +2535,7 @@ pub trait Iterator {
24972535
move |x, y| cmp::max_by(x, y, &mut compare)
24982536
}
24992537

2500-
fold1(self, fold(compare))
2538+
self.fold_first(fold(compare))
25012539
}
25022540

25032541
/// Returns the element that gives the minimum value from the
@@ -2561,7 +2599,7 @@ pub trait Iterator {
25612599
move |x, y| cmp::min_by(x, y, &mut compare)
25622600
}
25632601

2564-
fold1(self, fold(compare))
2602+
self.fold_first(fold(compare))
25652603
}
25662604

25672605
/// Reverses an iterator's direction.
@@ -3214,20 +3252,6 @@ pub trait Iterator {
32143252
}
32153253
}
32163254

3217-
/// Fold an iterator without having to provide an initial value.
3218-
#[inline]
3219-
fn fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
3220-
where
3221-
I: Iterator,
3222-
F: FnMut(I::Item, I::Item) -> I::Item,
3223-
{
3224-
// start with the first element as our selection. This avoids
3225-
// having to use `Option`s inside the loop, translating to a
3226-
// sizeable performance gain (6x in one case).
3227-
let first = it.next()?;
3228-
Some(it.fold(first, f))
3229-
}
3230-
32313255
#[stable(feature = "rust1", since = "1.0.0")]
32323256
impl<I: Iterator + ?Sized> Iterator for &mut I {
32333257
type Item = I::Item;

0 commit comments

Comments
 (0)