diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-03-27 15:09:48 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-27 15:09:48 +0100 |
| commit | 87fdf35572089028dff6bf4eb620c2f99764c1e0 (patch) | |
| tree | 4cf31fd8ec3af094dbe8fa2ab968f26f56928da1 /src | |
| parent | 697d6b3f3fa1f163acb5ae0911d7df7f02a54444 (diff) | |
| parent | 268408f495f5fe225269842837ec1e49b498c881 (diff) | |
| download | rust-87fdf35572089028dff6bf4eb620c2f99764c1e0.tar.gz rust-87fdf35572089028dff6bf4eb620c2f99764c1e0.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/iter/traits/iterator.rs | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 39bd270da86..daa880e7cd5 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -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; |
