]> git.lizzy.rs Git - rust.git/commitdiff
core: Refactor iterators
authorPiotr Czarnecki <pioczarn@gmail.com>
Wed, 6 Aug 2014 10:20:37 +0000 (11:20 +0100)
committerPiotr Czarnecki <pioczarn@gmail.com>
Wed, 6 Aug 2014 10:20:37 +0000 (11:20 +0100)
Simplifying the code of methods: nth, fold, rposition
and iterators: Filter, FilterMap, SkipWhile
Adding basic benchmarks

src/libcore/iter.rs
src/libcoretest/iter.rs

index b0660230c2ce6923efe3f10409f0555baf936a22..b8ed8bdf9239402d7e0e97c36c971a66ac12e1c4 100644 (file)
@@ -481,13 +481,11 @@ fn collect<B: FromIterator<A>>(&mut self) -> B {
     /// ```
     #[inline]
     fn nth(&mut self, mut n: uint) -> Option<A> {
-        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 @@ fn last(&mut self) -> Option<A> {
     #[inline]
     fn fold<B>(&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<A> : DoubleEndedIterator<A> {
     /// If no element matches, None is returned.
     #[inline]
     fn rposition(&mut self, predicate: |A| -> bool) -> Option<uint> {
-        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 @@ fn rposition(&mut self, predicate: |A| -> bool) -> Option<uint> {
     /// 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 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 impl<'a, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Filter<'a, A, T> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
-        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<A>> DoubleEndedIterator<B>
 for FilterMap<'a, A, B, T> {
     #[inline]
     fn next_back(&mut self) -> Option<B> {
-        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<A>> Iterator<A> for SkipWhile<'a, A, T> {
     #[inline]
     fn next(&mut self) -> Option<A> {
-        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]
index cadbc238e679ad1d7144a2f9629f6a87b4946e8a..d25ffb5b84c8a6aa926bc34e540a1bdfc9e0f214 100644 (file)
@@ -14,6 +14,8 @@
 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<uint> = 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);
+        }
+    });
+}