Skip to content

Commit d3d163a

Browse files
committed
impl fold_first
1 parent bb6e76d commit d3d163a

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

library/core/src/iter/traits/iterator.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,13 +2448,12 @@ pub trait Iterator {
24482448
/// ```
24492449
#[inline]
24502450
#[stable(feature = "iterator_fold_self", since = "1.51.0")]
2451-
fn reduce<F>(mut self, f: F) -> Option<Self::Item>
2451+
fn reduce<F>(self, f: F) -> Option<Self::Item>
24522452
where
24532453
Self: Sized,
24542454
F: FnMut(Self::Item, Self::Item) -> Self::Item,
24552455
{
2456-
let first = self.next()?;
2457-
Some(self.fold(first, f))
2456+
self.fold_first(core::convert::identity, f)
24582457
}
24592458

24602459
/// Reduces the elements to a single one by repeatedly applying a reducing operation. If the
@@ -2537,6 +2536,53 @@ pub trait Iterator {
25372536
}
25382537
}
25392538

2539+
/// Folds every element into an accumulator by applying an operation,
2540+
/// returning the final result. The initial value is derived from the
2541+
/// first element using the provided method.
2542+
///
2543+
/// If the iterator is empty, returns [`None`]; otherwise, returns the
2544+
/// result of the fold.
2545+
///
2546+
/// The folding function is a closure with two arguments: an 'accumulator', and an element.
2547+
/// For iterators with at least one element, this is the same as [`reduce()`]
2548+
/// with the first element being fed into the init function
2549+
///
2550+
/// [`reduce()`]: Iterator::reduce
2551+
///
2552+
/// # Example
2553+
///
2554+
/// ```
2555+
/// #![feature(iterator_fold_first)]
2556+
///
2557+
/// let min_max: (i32, i32) = [3, 1, 4, 1, 5, 9, 2]
2558+
/// .into_iter()
2559+
/// .fold_first(
2560+
/// |first| (first, first),
2561+
/// |(min, max), next| (i32::min(min, next), i32::max(max, next)),
2562+
/// ).unwrap();
2563+
/// assert_eq!(min_max, (1, 9));
2564+
///
2565+
/// // Which is equivalent to doing it with `fold`:
2566+
/// let folded: (i32, i32) = [3, 1, 4, 1, 5, 9, 2]
2567+
/// .into_iter()
2568+
/// .fold(
2569+
/// (i32::MAX, i32::MIN),
2570+
/// |(min, max), next| (i32::min(min, next), i32::max(max, next)),
2571+
/// );
2572+
/// assert_eq!(min_max, folded);
2573+
/// ```
2574+
#[inline]
2575+
#[unstable(feature = "iterator_fold_first", reason = "new API", issue = "none")]
2576+
fn fold_first<B, F1, FR>(mut self, init: F1, folding: FR) -> Option<B>
2577+
where
2578+
Self: Sized,
2579+
F1: FnOnce(Self::Item) -> B,
2580+
FR: FnMut(B, Self::Item) -> B,
2581+
{
2582+
let first = init(self.next()?);
2583+
Some(self.fold(first, folding))
2584+
}
2585+
25402586
/// Tests if every element of the iterator matches a predicate.
25412587
///
25422588
/// `all()` takes a closure that returns `true` or `false`. It applies

0 commit comments

Comments
 (0)