diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 3063cb1a7df44..70aacfa5eb8bb 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1586,6 +1586,46 @@ pub trait Iterator { Try::from_ok(accum) } + /// The same as [`try_fold()`](#method.try_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. + /// + /// # Examples + /// + /// Find the maximum value: + /// + /// ``` + /// use std::cmp::Ordering; + /// fn find_max(iter: I) -> Option + /// where I: Iterator, + /// I::Item: PartialCmp, + /// { + /// iter.try_fold_self(|a, b| { + /// a.partial_cmp(b).map(move |cmp| match cmp { + /// Ordering::Greater | Ordering::Equal => a, + /// Ordering::Less => b, + /// }) + /// }) + /// } + /// let a = [10, 20, 5, -23, 0]; + /// let b = [10, 20, -23, std::f64::NAN, 12, 2.5]; + /// let c = []; + /// + /// assert_eq!(find_max(a.iter()), Some(Some(20))); + /// assert_eq!(find_max(b.iter()), Some(None)); + /// assert_eq!(find_max(c.iter()), None); + /// ``` + #[inline] + #[unstable(feature = "iterator_fold_self", issue = "60103")] + fn try_fold_self(&mut self, mut f: F) -> Option + where Self: Sized, + F: FnMut(Self::Item, Self::Item) -> R, + R: Try + { + self.next().map(move |first| self.try_fold(first, f)) + } + /// An iterator method that applies a fallible function to each item in the /// iterator, stopping at the first error and returning that error. /// @@ -1696,6 +1736,41 @@ pub trait Iterator { self.try_fold(init, move |acc, x| Ok::(f(acc, x))).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: + /// + /// ``` + /// fn find_max(iter: I) -> Option + /// where I: Iterator, + /// I::Item: Ord, + /// { + /// iter.fold_self(|a, b| { + /// a.partial_cmp(b).map(move |cmp| match cmp { + /// Ordering::Greater | Ordering::Equal => a, + /// Ordering::Less => b, + /// }) + /// }) + /// } + /// let a = [10, 20, 5, -23, 0]; + /// let b = []; + /// + /// assert_eq!(find_max(a.iter()), Some(20)); + /// assert_eq!(find_max(b.iter()), None)); + /// ``` + #[inline] + #[unstable(feature = "iterator_fold_self", issue = "60103")] + fn fold_self(mut self, mut f: F) -> Option + where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item + { + self.next().map(move |first| 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