From 561f1b006321501dfe5a059444fc8f560010c2ba Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 14 Sep 2013 16:33:19 -0400 Subject: [PATCH 1/4] iter: fix range docstrings --- src/libstd/iter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index ec3c02a31f2f5..a0de8b1efada9 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1719,7 +1719,7 @@ pub fn count(start: A, step: A) -> Counter { Counter{state: start, step: step} } -/// A range of numbers from [0, N) +/// An iterator over the range [start, stop) #[deriving(Clone, DeepClone)] pub struct Range { priv state: A, @@ -1765,7 +1765,7 @@ impl + Integer + Ord + Clone> DoubleEndedIterator for Range { } } -/// A range of numbers from [0, N] +/// An iterator over the range [start, stop] #[deriving(Clone, DeepClone)] pub struct RangeInclusive { priv range: Range, From 10c8978edbb53fda8b33758a0bf3f9154b20dc9e Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 14 Sep 2013 16:34:32 -0400 Subject: [PATCH 2/4] iter: replace comment with a docstring --- src/libstd/iter.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index a0de8b1efada9..8407b0683446d 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1749,14 +1749,12 @@ impl + Ord + Clone> Iterator for Range { // Blocked on #8605 Need numeric trait for converting to `Option` } -impl + Integer + Ord + Clone> DoubleEndedIterator for Range { +/// `Integer` is required to ensure the range will be the same regardless of +/// the direction it is consumed. +impl DoubleEndedIterator for Range { #[inline] fn next_back(&mut self) -> Option { if self.stop > self.state { - // Integer doesn't technically define this rule, but we're going to assume that every - // Integer is reachable from every other one by adding or subtracting enough Ones. This - // seems like a reasonable-enough rule that every Integer should conform to, even if it - // can't be statically checked. self.stop = self.stop - self.one; Some(self.stop.clone()) } else { From 3aead52586d26f375e6318fb6980280db18b70b7 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 14 Sep 2013 16:37:52 -0400 Subject: [PATCH 3/4] iter: move Counter impl to the proper place --- src/libstd/iter.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 8407b0683446d..faa2d715df48c 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1719,6 +1719,20 @@ pub fn count(start: A, step: A) -> Counter { Counter{state: start, step: step} } +impl + Clone> Iterator for Counter { + #[inline] + fn next(&mut self) -> Option { + let result = self.state.clone(); + self.state = self.state + self.step; + Some(result) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (uint::max_value, None) // Too bad we can't specify an infinite lower bound + } +} + /// An iterator over the range [start, stop) #[deriving(Clone, DeepClone)] pub struct Range { @@ -1824,20 +1838,6 @@ impl + Integer + Ord + Clone> DoubleEndedIterator for RangeInclu } } -impl + Clone> Iterator for Counter { - #[inline] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state + self.step; - Some(result) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (uint::max_value, None) // Too bad we can't specify an infinite lower bound - } -} - /// An iterator that repeats an element endlessly #[deriving(Clone, DeepClone)] pub struct Repeat { From a18038f3b2ee338de05ef4489d6ac7067c9198fd Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 14 Sep 2013 16:47:21 -0400 Subject: [PATCH 4/4] iter: add `RangeStep` and `RangeStepInclusive` --- src/libstd/iter.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index faa2d715df48c..22e8a1defbda9 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -21,7 +21,7 @@ use cmp; use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating}; use option::{Option, Some, None}; use ops::{Add, Mul, Sub}; -use cmp::Ord; +use cmp::{Eq, Ord}; use clone::Clone; use uint; use util; @@ -1838,6 +1838,81 @@ impl + Integer + Ord + Clone> DoubleEndedIterator for RangeInclu } } +/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[deriving(Clone, DeepClone)] +pub struct RangeStep { + priv state: A, + priv stop: A, + priv step: A, + priv rev: bool +} + +/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step(start: A, stop: A, step: A) -> RangeStep { + let rev = step < Zero::zero(); + RangeStep{state: start, stop: stop, step: step, rev: rev} +} + +impl Iterator for RangeStep { + #[inline] + fn next(&mut self) -> Option { + if (self.rev && self.state > self.stop) || self.state < self.stop { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.state = self.stop.clone() + } + Some(result) + } else { + None + } + } +} + +/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[deriving(Clone, DeepClone)] +pub struct RangeStepInclusive { + priv state: A, + priv stop: A, + priv step: A, + priv rev: bool, + priv done: bool +} + +/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step_inclusive(start: A, stop: A, + step: A) -> RangeStepInclusive { + let rev = step < Zero::zero(); + RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} +} + +impl Iterator for RangeStepInclusive { + #[inline] + fn next(&mut self) -> Option { + if !self.done { + if (self.rev && self.state > self.stop) || self.state < self.stop { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.done = true + } + Some(result) + } else { + if self.state == self.stop { + self.done = true; + Some(self.state.clone()) + } else { + None + } + } + } else { + None + } + } +} + /// An iterator that repeats an element endlessly #[deriving(Clone, DeepClone)] pub struct Repeat { @@ -2647,6 +2722,20 @@ mod tests { assert_eq!(range_inclusive(0i, 5).invert().collect::<~[int]>(), ~[5i, 4, 3, 2, 1, 0]); } + #[test] + fn test_range_step() { + assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15]); + assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5]); + assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + } + + #[test] + fn test_range_step_inclusive() { + assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15, 20]); + assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]); + assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + } + #[test] fn test_reverse() { let mut ys = [1, 2, 3, 4, 5];