Skip to content

Commit 2cb8340

Browse files
committed
iter: Special case .fold() for several adaptors
Chain and FlatMap can do something interesting here where they convert folds into sequences of folds on their inner iterators. This generally results in better code. Also implement .fold() specifically for .map() and .cloned() so that any inner fold improvements are available through map and cloned.
1 parent 0c42987 commit 2cb8340

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

src/libcore/iter/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,12 @@ impl<'a, I, T: 'a> Iterator for Cloned<I>
399399
fn size_hint(&self) -> (usize, Option<usize>) {
400400
self.it.size_hint()
401401
}
402+
403+
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
404+
where F: FnMut(Acc, Self::Item) -> Acc,
405+
{
406+
self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
407+
}
402408
}
403409

404410
#[stable(feature = "iter_cloned", since = "1.1.0")]
@@ -544,6 +550,25 @@ impl<A, B> Iterator for Chain<A, B> where
544550
}
545551
}
546552

553+
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
554+
where F: FnMut(Acc, Self::Item) -> Acc,
555+
{
556+
let mut accum = init;
557+
match self.state {
558+
ChainState::Both | ChainState::Front => {
559+
accum = self.a.fold(accum, &mut f);
560+
}
561+
_ => { }
562+
}
563+
match self.state {
564+
ChainState::Both | ChainState::Back => {
565+
accum = self.b.fold(accum, &mut f);
566+
}
567+
_ => { }
568+
}
569+
accum
570+
}
571+
547572
#[inline]
548573
fn nth(&mut self, mut n: usize) -> Option<A::Item> {
549574
match self.state {
@@ -939,6 +964,13 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
939964
fn size_hint(&self) -> (usize, Option<usize>) {
940965
self.iter.size_hint()
941966
}
967+
968+
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
969+
where G: FnMut(Acc, Self::Item) -> Acc,
970+
{
971+
let mut f = self.f;
972+
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
973+
}
942974
}
943975

944976
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1688,6 +1720,22 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
16881720
}
16891721
}
16901722

1723+
fn fold<Acc, G>(self, init: Acc, mut f: G) -> Acc
1724+
where G: FnMut(Acc, Self::Item) -> Acc,
1725+
{
1726+
let mut accum = init;
1727+
if let Some(iter) = self.frontiter {
1728+
accum = iter.fold(accum, &mut f);
1729+
}
1730+
for iter in self.iter.map(self.f) {
1731+
accum = iter.into_iter().fold(accum, &mut f);
1732+
}
1733+
if let Some(iter) = self.backiter {
1734+
accum = iter.fold(accum, &mut f);
1735+
}
1736+
accum
1737+
}
1738+
16911739
#[inline]
16921740
fn size_hint(&self) -> (usize, Option<usize>) {
16931741
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());

0 commit comments

Comments
 (0)