diff options
| author | kennytm <kennytm@gmail.com> | 2019-03-02 14:55:06 +0800 |
|---|---|---|
| committer | kennytm <kennytm@gmail.com> | 2019-03-02 22:58:11 +0800 |
| commit | 2e82d11de1709efe1b89ef73e71550c8fe28b7dd (patch) | |
| tree | 29f84e662598a0ca15f496f273549011478b6467 /src/libcore | |
| parent | d987b46bd7e81eb761a06252efb35b6d932a62f5 (diff) | |
| parent | 88bd624a88692dd4bbda5f3f324f0035dc041534 (diff) | |
| download | rust-2e82d11de1709efe1b89ef73e71550c8fe28b7dd.tar.gz rust-2e82d11de1709efe1b89ef73e71550c8fe28b7dd.zip | |
Rollup merge of #58730 - timvermeulen:internal_iteration, r=scottmcm
Have all methods of Filter and FilterMap use internal iteration
This PR changes `Filter::{next, next_back, count}` and `FilterMap::{next, next_back}` to all use internal iteration. The `next` and `next_back` methods are changed to directly forward to `try_for_each` and `try_rfold` respectively, using `Result` as the `Try` type. I think that's okay? Alternatively, I could change their implementations to use `LoopState` instead if there's any benefit in doing so.
r? @scottmcm
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/benches/iter.rs | 32 | ||||
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 37 |
2 files changed, 37 insertions, 32 deletions
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index fe852e42b5c..1dd2bd3ee78 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -185,13 +185,13 @@ bench_sums! { bench_sums! { bench_filter_sum, bench_filter_ref_sum, - (0i64..1000000).filter(|x| x % 2 == 0) + (0i64..1000000).filter(|x| x % 3 == 0) } bench_sums! { bench_filter_chain_sum, bench_filter_chain_ref_sum, - (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0) + (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0) } bench_sums! { @@ -306,3 +306,31 @@ fn bench_skip_then_zip(b: &mut Bencher) { assert_eq!(s, 2009900); }); } + +#[bench] +fn bench_filter_count(b: &mut Bencher) { + b.iter(|| { + (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count() + }) +} + +#[bench] +fn bench_filter_ref_count(b: &mut Bencher) { + b.iter(|| { + (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count() + }) +} + +#[bench] +fn bench_filter_chain_count(b: &mut Bencher) { + b.iter(|| { + (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count() + }) +} + +#[bench] +fn bench_filter_chain_ref_count(b: &mut Bencher) { + b.iter(|| { + (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count() + }) +} diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index bca1b76dbb9..d4ad22c16bb 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -681,12 +681,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool #[inline] fn next(&mut self) -> Option<I::Item> { - for x in &mut self.iter { - if (self.predicate)(&x) { - return Some(x); - } - } - None + self.try_for_each(Err).err() } #[inline] @@ -707,12 +702,9 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool // Using the branchless version will also simplify the LLVM byte code, thus // leaving more budget for LLVM optimizations. #[inline] - fn count(mut self) -> usize { - let mut count = 0; - for x in &mut self.iter { - count += (self.predicate)(&x) as usize; - } - count + fn count(self) -> usize { + let mut predicate = self.predicate; + self.iter.map(|x| predicate(&x) as usize).sum() } #[inline] @@ -746,12 +738,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> { #[inline] fn next_back(&mut self) -> Option<I::Item> { - for x in self.iter.by_ref().rev() { - if (self.predicate)(&x) { - return Some(x); - } - } - None + self.try_rfold((), |_, x| Err(x)).err() } #[inline] @@ -820,12 +807,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> #[inline] fn next(&mut self) -> Option<B> { - for x in self.iter.by_ref() { - if let Some(y) = (self.f)(x) { - return Some(y); - } - } - None + self.try_for_each(Err).err() } #[inline] @@ -863,12 +845,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> { #[inline] fn next_back(&mut self) -> Option<B> { - for x in self.iter.by_ref().rev() { - if let Some(y) = (self.f)(x) { - return Some(y); - } - } - None + self.try_rfold((), |_, x| Err(x)).err() } #[inline] |
