From a16626fc422f9fdcd1d02f56b628f764d5282261 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 25 Oct 2016 15:21:49 +0200 Subject: [PATCH] iter: Implement .fold() for .chain() Chain can do something interesting here where it passes on the fold into its inner iterators. The lets the underlying iterator's custom fold() be used, and skips the regular chain logic in next. --- src/libcore/iter/mod.rs | 19 +++++++++++++++++++ src/libcoretest/iter.rs | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 2c3b8864a115..df4f5e5c5764 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -550,6 +550,25 @@ impl Iterator for Chain where } } + fn fold(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.fold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.fold(accum, &mut f); + } + _ => { } + } + accum + } + #[inline] fn nth(&mut self, mut n: usize) -> Option { match self.state { diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 27eb25537f31..58b6444ef88c 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -985,6 +985,18 @@ fn test_empty() { assert_eq!(it.next(), None); } +#[test] +fn test_chain_fold() { + let xs = [1, 2, 3]; + let ys = [1, 2, 0]; + + let mut iter = xs.iter().chain(&ys); + iter.next(); + let mut result = Vec::new(); + iter.fold((), |(), &elt| result.push(elt)); + assert_eq!(&[2, 3, 1, 2, 0], &result[..]); +} + #[bench] fn bench_rposition(b: &mut Bencher) { let it: Vec = (0..300).collect();