diff options
| author | Nicholas Nethercote <nnethercote@mozilla.com> | 2020-05-18 09:34:34 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <nnethercote@mozilla.com> | 2020-05-18 16:51:39 +1000 |
| commit | 959bd48887d431a0f30090af18ef40d8c5606d77 (patch) | |
| tree | 7a05666990075e52f6389696bc7be72ab3a159e4 | |
| parent | c2abf8f9c30a979ca756ed84e085e3507c3227e9 (diff) | |
| download | rust-959bd48887d431a0f30090af18ef40d8c5606d77.tar.gz rust-959bd48887d431a0f30090af18ef40d8c5606d77.zip | |
Add some more `rfold` implementations.
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 53 | ||||
| -rw-r--r-- | src/libcore/iter/range.rs | 15 |
2 files changed, 68 insertions, 0 deletions
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 939a26cb702..195847ee98d 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -724,6 +724,29 @@ where } } } + + #[inline] + fn rfold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn nth_back<I: DoubleEndedIterator>( + iter: &mut I, + step: usize, + ) -> impl FnMut() -> Option<I::Item> + '_ { + move || iter.nth_back(step) + } + + match self.next_back() { + None => init, + Some(x) => { + let acc = f(init, x); + from_fn(nth_back(&mut self.iter, self.step)).fold(acc, f) + } + } + } } // StepBy can only make the iterator shorter, so the len will still fit. @@ -2056,6 +2079,18 @@ where self.iter.try_rfold(init, check(n, fold)).into_try() } } + + fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(init, ok(fold)).unwrap() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -2220,6 +2255,24 @@ where } } } + + #[inline] + fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if self.n == 0 { + init + } else { + let len = self.iter.len(); + if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() { + init + } else { + self.iter.rfold(init, fold) + } + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 6ac9576a46d..388a5548a31 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -671,6 +671,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> { self.try_fold(init, ok(f)).unwrap() } + #[inline] fn last(mut self) -> Option<A> { self.next_back() @@ -759,6 +760,20 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> { Try::from_ok(accum) } + + #[inline] + fn rfold<B, F>(mut self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + #[inline] + fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(init, ok(f)).unwrap() + } } #[unstable(feature = "trusted_len", issue = "37572")] |
