@@ -69,34 +69,53 @@ pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
6969pub pure fn is_nonnegative ( x : T ) -> bool { x >= 0 as T }
7070
7171#[ inline( always) ]
72- /// Iterate over the range [`start`,`start`+`step`..`stop`)
73- pub pure fn range_step ( start : T , stop : T , step : T , it : fn ( T ) -> bool ) {
72+ /**
73+ * Iterate over the range [`start`,`start`+`step`..`stop`)
74+ *
75+ * Note that `uint` requires separate `range_step` functions for each
76+ * direction.
77+ *
78+ */
79+ pub pure fn range_step_up ( start : T , stop : T , step : T , it : fn ( T ) -> bool ) {
7480 let mut i = start;
7581 if step == 0 {
76- fail ~"range_step called with step == 0 ";
77- } else if step > 0 { // ascending
78- while i < stop {
79- if !it ( i) { break }
80- i += step;
81- }
82- } else { // descending
83- while i > stop {
84- if !it ( i) { break }
85- i += step;
86- }
82+ fail ~"range_step_up called with step == 0 ";
83+ }
84+ while i < stop {
85+ if !it ( i) { break }
86+ i += step;
87+ }
88+ }
89+
90+ #[ inline( always) ]
91+ /**
92+ * Iterate over the range [`start`,`start`-`step`..`stop`)
93+ *
94+ * Note that `uint` requires separate `range_step` functions for each
95+ * direction.
96+ *
97+ */
98+ pub pure fn range_step_down ( start : T , stop : T , step : T , it : fn ( T ) -> bool ) {
99+ let mut i = start;
100+ if step == 0 {
101+ fail ~"range_step_down called with step == 0 ";
102+ }
103+ while i > stop {
104+ if !it ( i) { break }
105+ i -= step;
87106 }
88107}
89108
90109#[ inline( always) ]
91110/// Iterate over the range [`lo`..`hi`)
92111pub pure fn range ( lo : T , hi : T , it : fn ( T ) -> bool ) {
93- range_step ( lo, hi, 1 as T , it) ;
112+ range_step_up ( lo, hi, 1 as T , it) ;
94113}
95114
96115#[ inline( always) ]
97116/// Iterate over the range [`hi`..`lo`)
98117pub pure fn range_rev ( hi : T , lo : T , it : fn ( T ) -> bool ) {
99- range_step ( hi, lo, - 1 as T , it) ;
118+ range_step_down ( hi, lo, 1 as T , it) ;
100119}
101120
102121/// Computes the bitwise complement
@@ -351,3 +370,51 @@ pub fn test_times() {
351370 for ten. times { accum += 1 ; }
352371 assert ( accum == 10 ) ;
353372}
373+ use io;
374+ #[ test]
375+ pub fn test_ranges ( ) {
376+ let mut l = ~[ ] ;
377+
378+ for range( 0 , 3 ) |i| {
379+ l. push ( i) ;
380+ }
381+ for range_rev( 13 , 10 ) |i| {
382+ l. push ( i) ;
383+ }
384+ for range_step_up( 20 , 26 , 2 ) |i| {
385+ l. push ( i) ;
386+ }
387+ for range_step_down( 36 , 30 , 2 ) |i| {
388+ l. push ( i) ;
389+ }
390+
391+ assert l == ~[ 0 , 1 , 2 ,
392+ 13 , 12 , 11 ,
393+ 20 , 22 , 24 ,
394+ 36 , 34 , 32 ] ;
395+
396+ // None of the `fail`s should execute.
397+ for range( 0 , 0 ) |_i| {
398+ fail ~"unreachable";
399+ }
400+ for range_rev( 0 , 0 ) |_i| {
401+ fail ~"unreachable";
402+ }
403+ for range_step_up( 10 , 0 , 1 ) |_i| {
404+ fail ~"unreachable";
405+ }
406+ for range_step_down( 0 , 10 , 1 ) |_i| {
407+ fail ~"unreachable";
408+ }
409+ }
410+
411+ #[ test]
412+ #[ should_fail]
413+ fn test_range_step_up_zero_step( ) {
414+ for range_step_up( 0 , 10 , 0 ) |_i| { }
415+ }
416+ #[ test]
417+ #[ should_fail]
418+ fn test_range_step_down_zero_step( ) {
419+ for range_step_down( 0 , 10 , 0 ) |_i| { }
420+ }
0 commit comments