about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2012-02-12 20:05:55 -0800
committerBrian Anderson <andersrb@gmail.com>2012-02-12 20:05:55 -0800
commit2784314a1ff4f9b5230abb44c86b09d74d6b5e73 (patch)
tree006a7f7caf6e549b3e17826a92ee9657cf9cf9fe
parent4eeb706e84bc9e32aa5057e32d567ccab2c3cc2c (diff)
parentfde719f635955b1c3d76639062410262fd0df351 (diff)
downloadrust-2784314a1ff4f9b5230abb44c86b09d74d6b5e73.tar.gz
rust-2784314a1ff4f9b5230abb44c86b09d74d6b5e73.zip
Merge pull request #1826 from brson/iter
Various additions to core::iter
-rw-r--r--src/libcore/iter.rs99
1 files changed, 97 insertions, 2 deletions
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 7aa08a6980c..c2fc2838d70 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -65,18 +65,43 @@ fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
     }
 }
 
-fn foldl<A,B:copy,IA:iterable<A>>(self: IA, b0: B, blk: fn(B, A) -> B) -> B {
-    let b = b0;
+fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
+    let b <- b0;
     self.iter {|a|
         b = blk(b, a);
     }
     ret b;
 }
 
+fn foldr<A:copy,B,IA:iterable<A>>(
+    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {
+
+    let b <- b0;
+    reverse(self) {|a|
+        b = blk(a, b);
+    }
+    ret b;
+}
+
 fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
     foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
 }
 
+// FIXME: This could be made more efficient with an riterable interface
+fn reverse<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
+    vec::riter(to_list(self), blk)
+}
+
+fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
+    foldl(self, 0u) {|count, value|
+        if value == x {
+            count + 1u
+        } else {
+            count
+        }
+    }
+}
+
 fn repeat(times: uint, blk: fn()) {
     let i = 0u;
     while i < times {
@@ -85,6 +110,35 @@ fn repeat(times: uint, blk: fn()) {
     }
 }
 
+fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
+    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
+        alt a {
+          some(a_) if a_ < b {
+            // FIXME: Not sure if this is successfully optimized to a move
+            a
+          }
+          _ { some(b) }
+        }
+    } {
+        some(val) { val }
+        none { fail "min called on empty iterator" }
+    }
+}
+
+fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
+    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
+        alt a {
+          some(a_) if a_ > b {
+            // FIXME: Not sure if this is successfully optimized to a move
+            a
+          }
+          _ { some(b) }
+        }
+    } {
+        some(val) { val }
+        none { fail "max called on empty iterator" }
+    }
+}
 
 #[test]
 fn test_enumerate() {
@@ -168,4 +222,45 @@ fn test_repeat() {
     assert c == [0u, 1u, 4u, 9u, 16u];
 }
 
+#[test]
+fn test_min() {
+    assert min([5, 4, 1, 2, 3]) == 1;
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(target_os = "win32"))]
+fn test_min_empty() {
+    min::<int, [int]>([]);
+}
+
+#[test]
+fn test_max() {
+    assert max([1, 2, 4, 2, 3]) == 4;
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(target_os = "win32"))]
+fn test_max_empty() {
+    max::<int, [int]>([]);
+}
 
+#[test]
+fn test_reverse() {
+    assert to_list(bind reverse([1, 2, 3], _)) == [3, 2, 1];
+}
+
+#[test]
+fn test_count() {
+    assert count([1, 2, 1, 2, 1], 1) == 3u;
+}
+
+#[test]
+fn test_foldr() {
+    fn sub(&&a: int, -b: int) -> int {
+        a - b
+    }
+    let sum = foldr([1, 2, 3, 4], 0, sub);
+    assert sum == -2;
+}
\ No newline at end of file