From 959bd48887d431a0f30090af18ef40d8c5606d77 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 May 2020 09:34:34 +1000 Subject: [PATCH] Add some more `rfold` implementations. --- src/libcore/iter/adapters/mod.rs | 53 ++++++++++++++++++++++++++++++++ src/libcore/iter/range.rs | 15 +++++++++ 2 files changed, 68 insertions(+) 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(mut self, init: Acc, mut f: F) -> Acc + where + Self: Sized, + F: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn nth_back( + iter: &mut I, + step: usize, + ) -> impl FnMut() -> Option + '_ { + 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(mut self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + #[inline] + fn ok(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result { + 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(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 Iterator for ops::RangeInclusive { self.try_fold(init, ok(f)).unwrap() } + #[inline] fn last(mut self) -> Option { self.next_back() @@ -759,6 +760,20 @@ impl DoubleEndedIterator for ops::RangeInclusive { Try::from_ok(accum) } + + #[inline] + fn rfold(mut self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + #[inline] + fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(init, ok(f)).unwrap() + } } #[unstable(feature = "trusted_len", issue = "37572")]