about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2012-07-17 13:54:24 -0400
committerBen Blum <bblum@andrew.cmu.edu>2012-07-17 13:57:36 -0400
commitbc87e66355e658cffb84396d1783364e23ddc6d2 (patch)
treeccc465bac6152c6dd04d666d60d0fea100a88021
parent85e79a3a8a52e339040a8533ba272a5891a62ce5 (diff)
downloadrust-bc87e66355e658cffb84396d1783364e23ddc6d2.tar.gz
rust-bc87e66355e658cffb84396d1783364e23ddc6d2.zip
Add option::while_some; also add more pure (close #2927)
-rw-r--r--src/libcore/option.rs42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 80b3915cb90..dabfa04ef24 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -52,6 +52,16 @@ pure fn chain<T, U>(opt: option<T>, f: fn(T) -> option<U>) -> option<U> {
     alt opt { some(x) { f(x) } none { none } }
 }
 
+#[inline(always)]
+pure fn while_some<T>(+x: option<T>, blk: fn(+T) -> option<T>) {
+    //! Applies a function zero or more times until the result is none.
+
+    let mut opt <- x;
+    while opt.is_some() {
+        opt = blk(unwrap(opt));
+    }
+}
+
 pure fn is_none<T>(opt: option<T>) -> bool {
     //! Returns true if the option equals `none`
 
@@ -106,18 +116,18 @@ impl extensions<T> for option<T> {
      * Update an optional value by optionally running its content through a
      * function that returns an option.
      */
-    fn chain<U>(f: fn(T) -> option<U>) -> option<U> { chain(self, f) }
+    pure fn chain<U>(f: fn(T) -> option<U>) -> option<U> { chain(self, f) }
     /// Applies a function to the contained value or returns a default
-    fn map_default<U: copy>(def: U, f: fn(T) -> U) -> U
+    pure fn map_default<U: copy>(def: U, f: fn(T) -> U) -> U
         { map_default(self, def, f) }
     /// Performs an operation on the contained value or does nothing
-    fn iter(f: fn(T)) { iter(self, f) }
+    pure fn iter(f: fn(T)) { iter(self, f) }
     /// Returns true if the option equals `none`
-    fn is_none() -> bool { is_none(self) }
+    pure fn is_none() -> bool { is_none(self) }
     /// Returns true if the option contains some value
-    fn is_some() -> bool { is_some(self) }
+    pure fn is_some() -> bool { is_some(self) }
     /// Maps a `some` value from one type to another
-    fn map<U:copy>(f: fn(T) -> U) -> option<U> { map(self, f) }
+    pure fn map<U:copy>(f: fn(T) -> U) -> option<U> { map(self, f) }
 }
 
 impl extensions<T: copy> for option<T> {
@@ -128,8 +138,8 @@ impl extensions<T: copy> for option<T> {
      *
      * Fails if the value equals `none`
      */
-    fn get() -> T { get(self) }
-    fn get_default(def: T) -> T { get_default(self, def) }
+    pure fn get() -> T { get(self) }
+    pure fn get_default(def: T) -> T { get_default(self, def) }
     /**
      * Gets the value out of an option, printing a specified message on
      * failure
@@ -139,6 +149,8 @@ impl extensions<T: copy> for option<T> {
      * Fails if the value equals `none`
      */
     pure fn expect(reason: ~str) -> T { expect(self, reason) }
+    /// Applies a function zero or more times until the result is none.
+    pure fn while_some(blk: fn(+T) -> option<T>) { while_some(self, blk) }
 }
 
 #[test]
@@ -177,6 +189,20 @@ fn test_unwrap_resource() {
     assert *i == 1;
 }
 
+#[test]
+fn test_option_while_some() {
+    let mut i = 0;
+    do some(10).while_some |j| {
+        i += 1;
+        if (j > 0) {
+            some(j-1)
+        } else {
+            none
+        }
+    }
+    assert i == 11;
+}
+
 // Local Variables:
 // mode: rust;
 // fill-column: 78;