diff options
| author | bors <bors@rust-lang.org> | 2013-07-03 01:07:55 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-07-03 01:07:55 -0700 |
| commit | ea31b9cca1e63a01fa75874cebca3f72f46ae029 (patch) | |
| tree | 5d8646f3851236de2822d05fded96c75fe75a43b /src/libstd | |
| parent | 025dc6e64ef364e0978c7a7b07ce1aeedf9810e5 (diff) | |
| parent | 3fe05a987c0d1684b1172ca29c9a9ad79852419e (diff) | |
| download | rust-ea31b9cca1e63a01fa75874cebca3f72f46ae029.tar.gz rust-ea31b9cca1e63a01fa75874cebca3f72f46ae029.zip | |
auto merge of #7474 : Seldaek/rust/clean-iter, r=thestinger
I think it's WIP - but I wanted to ask for feedback (/cc @thestinger) I had to move the impl of FromIter for vec into extra::iter because I don't think std can depend on extra, but that's a bit messed up. Similarly some FromIter uses are gone now, not sure if this is fixable or if I made a complete mess here..
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/iter.rs | 307 | ||||
| -rw-r--r-- | src/libstd/prelude.rs | 2 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 10 |
3 files changed, 6 insertions, 313 deletions
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 4e598a4aa1c..2092ae588d0 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -8,316 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! Composable internal iterators - -Internal iterators are functions implementing the protocol used by the `for` loop. - -An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal -breaking out of iteration. The adaptors in the module work with any such iterator, not just ones -tied to specific traits. For example: +/*! Times trait ~~~ {.rust} -println(iter::to_vec(|f| uint::range(0, 20, f)).to_str()); +use iter::Times; +let ten = 10 as uint; +let mut accum = 0; +for ten.times { accum += 1; } ~~~ -An external iterator object implementing the interface in the `iterator` module can be used as an -internal iterator by calling the `advance` method. For example: - -~~~ {.rust} -let xs = [0u, 1, 2, 3, 4, 5]; -let ys = [30, 40, 50, 60]; -let mut it = xs.iter().chain(ys.iter()); -for it.advance |&x: &uint| { - println(x.to_str()); -} -~~~ - -Internal iterators provide a subset of the functionality of an external iterator. It's not possible -to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often -much easier to implement. - */ -use cmp::Ord; -use option::{Option, Some, None}; -use num::{One, Zero}; -use ops::{Add, Mul}; - #[allow(missing_doc)] pub trait Times { fn times(&self, it: &fn() -> bool) -> bool; } -#[allow(missing_doc)] -pub trait FromIter<T> { - /// Build a container with elements from an internal iterator. - /// - /// # Example: - /// - /// ~~~ {.rust} - /// let xs = ~[1, 2, 3]; - /// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) }; - /// assert_eq!(xs, ys); - /// ~~~ - pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self; -} - -/** - * Return true if `predicate` is true for any values yielded by an internal iterator. - * - * Example: - * - * ~~~ {.rust} - * let xs = ~[1u, 2, 3, 4, 5]; - * assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f))); - * assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f))); - * ~~~ - */ -#[inline] -pub fn any<T>(predicate: &fn(T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { - for iter |x| { - if predicate(x) { - return true; - } - } - return false; -} - -/** - * Return true if `predicate` is true for all values yielded by an internal iterator. - * - * # Example: - * - * ~~~ {.rust} - * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); - * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); - * ~~~ - */ -#[inline] -pub fn all<T>(predicate: &fn(T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { - // If we ever break, iter will return false, so this will only return true - // if predicate returns true for everything. - iter(|x| predicate(x)) -} - -/** - * Return the first element where `predicate` returns `true`. Return `None` if no element is found. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[1u, 2, 3, 4, 5, 6]; - * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4); - * ~~~ - */ -#[inline] -pub fn find<T>(predicate: &fn(&T) -> bool, - iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - for iter |x| { - if predicate(&x) { - return Some(x); - } - } - None -} - -/** - * Return the largest item yielded by an iterator. Return `None` if the iterator is empty. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15); - * ~~~ - */ -#[inline] -pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - let mut result = None; - for iter |x| { - match result { - Some(ref mut y) => { - if x > *y { - *y = x; - } - } - None => result = Some(x) - } - } - result -} - -/** - * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty. - * - * # Example: - * - * ~~~ {.rust} - * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5); - * ~~~ - */ -#[inline] -pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { - let mut result = None; - for iter |x| { - match result { - Some(ref mut y) => { - if x < *y { - *y = x; - } - } - None => result = Some(x) - } - } - result -} - -/** - * Reduce an iterator to an accumulated value. - * - * # Example: - * - * ~~~ {.rust} - * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); - * ~~~ - */ -#[inline] -pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T { - let mut result = start; - for iter |x| { - f(&mut result, x); - } - result -} - -/** - * Reduce an iterator to an accumulated value. - * - * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it - * forces the iterator to yield borrowed pointers. - * - * # Example: - * - * ~~~ {.rust} - * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - * fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) - * } - * ~~~ - */ -#[inline] -pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T { - let mut result = start; - for iter |x| { - f(&mut result, x); - } - result -} - -/** - * Return the sum of the items yielding by an iterator. - * - * # Example: - * - * ~~~ {.rust} - * let xs: ~[int] = ~[1, 2, 3, 4]; - * assert_eq!(do sum |f| { xs.iter().advance(f) }, 10); - * ~~~ - */ -#[inline] -pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x)) -} - -/** - * Return the product of the items yielded by an iterator. - * - * # Example: - * - * ~~~ {.rust} - * let xs: ~[int] = ~[1, 2, 3, 4]; - * assert_eq!(do product |f| { xs.iter().advance(f) }, 24); - * ~~~ - */ -#[inline] -pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { - fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) -} - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - use int; - use uint; - - #[test] - fn test_from_iter() { - let xs = ~[1, 2, 3]; - let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) }; - assert_eq!(xs, ys); - } - - #[test] - fn test_any() { - let xs = ~[1u, 2, 3, 4, 5]; - assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f))); - assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f))); - } - - #[test] - fn test_all() { - assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f))); - assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f))); - } - - #[test] - fn test_find() { - let xs = ~[1u, 2, 3, 4, 5, 6]; - assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4); - } - - #[test] - fn test_max() { - let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15); - } - - #[test] - fn test_min() { - let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; - assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5); - } - - #[test] - fn test_fold() { - assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); - } - - #[test] - fn test_sum() { - let xs: ~[int] = ~[1, 2, 3, 4]; - assert_eq!(do sum |f| { xs.iter().advance(f) }, 10); - } - - #[test] - fn test_empty_sum() { - let xs: ~[int] = ~[]; - assert_eq!(do sum |f| { xs.iter().advance(f) }, 0); - } - - #[test] - fn test_product() { - let xs: ~[int] = ~[1, 2, 3, 4]; - assert_eq!(do product |f| { xs.iter().advance(f) }, 24); - } - - #[test] - fn test_empty_product() { - let xs: ~[int] = ~[]; - assert_eq!(do product |f| { xs.iter().advance(f) }, 1); - } -} diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index d560ce621ea..9d505209960 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -47,7 +47,7 @@ pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Great pub use char::Char; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; -pub use iter::{Times, FromIter}; +pub use iter::{Times}; pub use iterator::{Iterator, IteratorUtil, OrdIterator}; pub use num::{Num, NumCast}; pub use num::{Orderable, Signed, Unsigned, Round}; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 02eadaed5e8..28532bd54e3 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -19,7 +19,6 @@ use cmp; use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; use clone::Clone; use iterator::{FromIterator, Iterator, IteratorUtil}; -use iter::FromIter; use kinds::Copy; use libc; use libc::c_void; @@ -2168,15 +2167,6 @@ pub struct VecMutRevIterator<'self, T> { } iterator!{impl VecMutRevIterator -> &'self mut T, -1} -impl<T> FromIter<T> for ~[T]{ - #[inline] - pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { - let mut v = ~[]; - for iter |x| { v.push(x) } - v - } -} - #[cfg(stage0)] impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] { pub fn from_iterator(iterator: &mut T) -> ~[A] { |
