about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/core.rs22
-rw-r--r--src/libcore/int-template.rs35
-rw-r--r--src/libcore/iter.rs4
-rw-r--r--src/libcore/uint-template.rs26
4 files changed, 74 insertions, 13 deletions
diff --git a/src/libcore/core.rs b/src/libcore/core.rs
index f97d2727194..e70a092d876 100644
--- a/src/libcore/core.rs
+++ b/src/libcore/core.rs
@@ -12,16 +12,16 @@ import option_iter::extensions;
 import ptr::extensions;
 import rand::extensions;
 import result::extensions;
-import int::num;
-import i8::num;
-import i16::num;
-import i32::num;
-import i64::num;
-import uint::num;
-import u8::num;
-import u16::num;
-import u32::num;
-import u64::num;
+import int::{num, times};
+import i8::{num, times};
+import i16::{num, times};
+import i32::{num, times};
+import i64::{num, times};
+import uint::{num, times};
+import u8::{num, times};
+import u16::{num, times};
+import u32::{num, times};
+import u64::{num, times};
 import float::num;
 import f32::num;
 import f64::num;
@@ -29,7 +29,7 @@ import f64::num;
 export path, option, some, none, unreachable;
 export extensions;
 // The following exports are the extension impls for numeric types
-export num;
+export num, times;
 
 // Export the log levels as global constants. Higher levels mean
 // more-verbosity. Error is the bottom level, default logging level is
diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs
index 407b810e95d..5c5cffb2ac1 100644
--- a/src/libcore/int-template.rs
+++ b/src/libcore/int-template.rs
@@ -11,7 +11,7 @@ export range;
 export compl;
 export abs;
 export parse_buf, from_str, to_str, to_str_bytes, str;
-export num, ord, eq;
+export num, ord, eq, times;
 
 const min_value: T = -1 as T << (inst::bits - 1 as T);
 const max_value: T = min_value - 1 as T;
@@ -135,6 +135,25 @@ impl num of num::num for T {
     fn from_int(n: int) -> T   { ret n as T;      }
 }
 
+impl times of iter::times for T {
+    #[inline(always)]
+    #[doc = "A convenience form for basic iteration. Given a variable `x` \
+        of any numeric type, the expression `for x.times { /* anything */ }` \
+        will execute the given function exactly x times. If we assume that \
+        `x` is an int, this is functionally equivalent to \
+        `for int::range(0, x) |_i| { /* anything */ }`."]
+    fn times(it: fn() -> bool) {
+        if self < 0 {
+            fail #fmt("The .times method expects a nonnegative number, \
+                       but found %?", self);
+        }
+        let mut i = self;
+        while i > 0 {
+            if !it() { break }
+            i -= 1;
+        }
+    }
+}
 
 // FIXME: Has alignment issues on windows and 32-bit linux (#2609)
 #[test]
@@ -206,8 +225,22 @@ fn test_ifaces() {
         assert (ten.mul(two) == ten.from_int(20));
         assert (ten.div(two) == ten.from_int(5));
         assert (ten.modulo(two) == ten.from_int(0));
+        assert (ten.neg() == ten.from_int(-10));
     }
 
     test(10 as T);
 }
 
+#[test]
+fn test_times() {
+    let ten = 10 as T;
+    let mut accum = 0;
+    for ten.times { accum += 1; }
+    assert (accum == 10);
+}
+
+#[test]
+#[should_fail]
+fn test_times_negative() {
+    for (-10).times { log(error, "nope!"); }
+}
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 0280221ebfc..55d47cfe75d 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -3,6 +3,10 @@ iface base_iter<A> {
     fn size_hint() -> option<uint>;
 }
 
+iface times {
+    fn times(it: fn() -> bool);
+}
+
 fn eachi<A,IA:base_iter<A>>(self: IA, blk: fn(uint, A) -> bool) {
     let mut i = 0u;
     for self.each |a| {
diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs
index 91b9eb856e4..0433cd7ce30 100644
--- a/src/libcore/uint-template.rs
+++ b/src/libcore/uint-template.rs
@@ -11,7 +11,7 @@ export range;
 export compl;
 export to_str, to_str_bytes;
 export from_str, from_str_radix, str, parse_buf;
-export num, ord, eq;
+export num, ord, eq, times;
 
 const min_value: T = 0 as T;
 const max_value: T = 0 as T - 1 as T;
@@ -104,6 +104,22 @@ fn parse_buf(buf: ~[u8], radix: uint) -> option<T> {
     };
 }
 
+impl times of iter::times for T {
+    #[inline(always)]
+    #[doc = "A convenience form for basic iteration. Given a variable `x` \
+        of any numeric type, the expression `for x.times { /* anything */ }` \
+        will execute the given function exactly x times. If we assume that \
+        `x` is an int, this is functionally equivalent to \
+        `for int::range(0, x) |_i| { /* anything */ }`."]
+    fn times(it: fn() -> bool) {
+        let mut i = self;
+        while i > 0 {
+            if !it() { break }
+            i -= 1;
+        }
+    }
+}
+
 /// Parse a string to an int
 fn from_str(s: str) -> option<T> { parse_buf(str::bytes(s), 10u) }
 
@@ -259,3 +275,11 @@ fn to_str_radix1() {
 fn to_str_radix17() {
     uint::to_str(100u, 17u);
 }
+
+#[test]
+fn test_times() {
+    let ten = 10 as T;
+    let mut accum = 0;
+    for ten.times { accum += 1; }
+    assert (accum == 10);
+}