Skip to content

Commit 91318c8

Browse files
committed
core: Add DoubleEndedIterator::rfold
rfold is the reverse version of fold. Fold allows iterators to implement a different (non-resumable) internal iteration when it is more efficient than the external iteration implemented through the next method. (Common examples are VecDeque and .chain()). Introduce rfold() so that the same customization is available for reverse iteration. This is achieved by both adding the method, and by having the Rev<I> adaptor connect Rev::rfold -> I::fold, Rev::fold -> I::rfold.
1 parent ffd171e commit 91318c8

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

src/libcore/iter/traits.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,68 @@ pub trait DoubleEndedIterator: Iterator {
398398
#[stable(feature = "rust1", since = "1.0.0")]
399399
fn next_back(&mut self) -> Option<Self::Item>;
400400

401+
/// An iterator method that reduces the iterator's elements to a single,
402+
/// final value, starting from the back.
403+
///
404+
/// This is the reverse version of [`fold()`]: it takes elements starting from
405+
/// the back of the iterator.
406+
///
407+
/// `rfold()` takes two arguments: an initial value, and a closure with two
408+
/// arguments: an 'accumulator', and an element. The closure returns the value that
409+
/// the accumulator should have for the next iteration.
410+
///
411+
/// The initial value is the value the accumulator will have on the first
412+
/// call.
413+
///
414+
/// After applying this closure to every element of the iterator, `rfold()`
415+
/// returns the accumulator.
416+
///
417+
/// This operation is sometimes called 'reduce' or 'inject'.
418+
///
419+
/// Folding is useful whenever you have a collection of something, and want
420+
/// to produce a single value from it.
421+
///
422+
/// [`fold()`]: trait.Iterator.html#method.fold
423+
///
424+
/// # Examples
425+
///
426+
/// Basic usage:
427+
///
428+
/// ```
429+
/// let a = [1, 2, 3];
430+
///
431+
/// // the sum of all of the elements of a
432+
/// let sum = a.iter()
433+
/// .rfold(0, |acc, &x| acc + x);
434+
///
435+
/// assert_eq!(sum, 6);
436+
/// ```
437+
///
438+
/// This example builds a string, starting with an initial value
439+
/// and continuing with each element from the back until the front:
440+
///
441+
/// ```
442+
/// let numbers = [1, 2, 3, 4, 5];
443+
///
444+
/// let zero = "0".to_string();
445+
///
446+
/// let result = numbers.iter().rfold(zero, |acc, &x| {
447+
/// format!("({} + {})", x, acc)
448+
/// });
449+
///
450+
/// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
451+
/// ```
452+
#[inline]
453+
#[unstable(feature = "iter_rfold", issue = "0")]
454+
fn rfold<B, F>(mut self, mut accum: B, mut f: F) -> B where
455+
Self: Sized, F: FnMut(B, Self::Item) -> B,
456+
{
457+
while let Some(x) = self.next_back() {
458+
accum = f(accum, x);
459+
}
460+
accum
461+
}
462+
401463
/// Searches for an element of an iterator from the right that satisfies a predicate.
402464
///
403465
/// `rfind()` takes a closure that returns `true` or `false`. It applies

0 commit comments

Comments
 (0)