Skip to content

Commit

Permalink
Add some more rfold implementations.
Browse files Browse the repository at this point in the history
  • Loading branch information
nnethercote committed May 18, 2020
1 parent c2abf8f commit 959bd48
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/libcore/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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")]
Expand Down
15 changes: 15 additions & 0 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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")]
Expand Down

0 comments on commit 959bd48

Please sign in to comment.