From a55149b84eba79032567d3d107f73e7a71e358f6 Mon Sep 17 00:00:00 2001 From: Piotr Czarnecki Date: Wed, 6 Aug 2014 11:20:37 +0100 Subject: [PATCH] core: Refactor iterators Simplifying the code of methods: nth, fold, rposition and iterators: Filter, FilterMap, SkipWhile Adding basic benchmarks --- src/libcore/iter.rs | 86 ++++++++++++----------------------------- src/libcoretest/iter.rs | 31 +++++++++++++++ 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index b0660230c2c..b8ed8bdf923 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -481,13 +481,11 @@ pub trait Iterator { /// ``` #[inline] fn nth(&mut self, mut n: uint) -> Option { - loop { - match self.next() { - Some(x) => if n == 0 { return Some(x) }, - None => return None - } + for x in *self { + if n == 0 { return Some(x) } n -= 1; } + None } /// Loops through the entire iterator, returning the last element of the @@ -518,11 +516,8 @@ pub trait Iterator { #[inline] fn fold(&mut self, init: B, f: |B, A| -> B) -> B { let mut accum = init; - loop { - match self.next() { - Some(x) => { accum = f(accum, x); } - None => { break; } - } + for x in *self { + accum = f(accum, x); } accum } @@ -720,21 +715,10 @@ pub trait ExactSize : DoubleEndedIterator { /// If no element matches, None is returned. #[inline] fn rposition(&mut self, predicate: |A| -> bool) -> Option { - let (lower, upper) = self.size_hint(); - assert!(upper == Some(lower)); - let mut i = lower; - loop { - match self.next_back() { - None => break, - Some(x) => { - i = match i.checked_sub(&1) { - Some(x) => x, - None => fail!("rposition: incorrect ExactSize") - }; - if predicate(x) { - return Some(i) - } - } + let len = self.len(); + for i in range(0, len).rev() { + if predicate(self.next_back().expect("rposition: incorrect ExactSize")) { + return Some(i); } } None @@ -744,7 +728,7 @@ pub trait ExactSize : DoubleEndedIterator { /// Return the exact length of the iterator. fn len(&self) -> uint { let (lower, upper) = self.size_hint(); - assert!(upper == Some(lower)); + assert_eq!(upper, Some(lower)); lower } } @@ -1330,18 +1314,12 @@ impl<'a, A, T: Iterator> Iterator for Filter<'a, A, T> { impl<'a, A, T: DoubleEndedIterator> DoubleEndedIterator for Filter<'a, A, T> { #[inline] fn next_back(&mut self) -> Option { - loop { - match self.iter.next_back() { - None => return None, - Some(x) => { - if (self.predicate)(&x) { - return Some(x); - } else { - continue - } - } + for x in self.iter.by_ref().rev() { + if (self.predicate)(&x) { + return Some(x); } } + None } } @@ -1375,17 +1353,13 @@ impl<'a, A, B, T: DoubleEndedIterator> DoubleEndedIterator for FilterMap<'a, A, B, T> { #[inline] fn next_back(&mut self) -> Option { - loop { - match self.iter.next_back() { - None => return None, - Some(x) => { - match (self.f)(x) { - Some(y) => return Some(y), - None => () - } - } + for x in self.iter.by_ref().rev() { + match (self.f)(x) { + Some(y) => return Some(y), + None => () } } + None } } @@ -1507,25 +1481,13 @@ pub struct SkipWhile<'a, A, T> { impl<'a, A, T: Iterator> Iterator for SkipWhile<'a, A, T> { #[inline] fn next(&mut self) -> Option { - let mut next = self.iter.next(); - if self.flag { - next - } else { - loop { - match next { - Some(x) => { - if (self.predicate)(&x) { - next = self.iter.next(); - continue - } else { - self.flag = true; - return Some(x) - } - } - None => return None - } + for x in self.iter { + if self.flag || !(self.predicate)(&x) { + self.flag = true; + return Some(x); } } + None } #[inline] diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index cadbc238e67..d25ffb5b84c 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -14,6 +14,8 @@ use core::uint; use core::cmp; use core::num; +use test::Bencher; + #[test] fn test_lt() { let empty: [int, ..0] = []; @@ -270,6 +272,7 @@ fn test_iterator_nth() { for i in range(0u, v.len()) { assert_eq!(v.iter().nth(i).unwrap(), &v[i]); } + assert_eq!(v.iter().nth(v.len()), None); } #[test] @@ -842,3 +845,31 @@ fn test_iterate() { assert_eq!(it.next(), Some(4u)); assert_eq!(it.next(), Some(8u)); } + +#[bench] +fn bench_rposition(b: &mut Bencher) { + let it: Vec = range(0u, 300).collect(); + b.iter(|| { + it.iter().rposition(|&x| x <= 150); + }); +} + +#[bench] +fn bench_skip_while(b: &mut Bencher) { + b.iter(|| { + let it = range(0u, 100); + let mut sum = 0; + it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true); + }); +} + +#[bench] +fn bench_multiple_take(b: &mut Bencher) { + let mut it = range(0u, 42).cycle(); + b.iter(|| { + let n = it.next().unwrap(); + for m in range(0u, n) { + it.take(it.next().unwrap()).all(|_| true); + } + }); +}