Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic Iterator::collect() method #6980

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/librustc/util/enum_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,19 @@ mod test {
fn test_each() {
let mut e1: EnumSet<Foo> = EnumSet::empty();

assert_eq!(~[], iter::to_vec(|f| e1.each(f)))
assert_eq!(~[], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e1.each(f)))

e1.add(A);
assert_eq!(~[A], iter::to_vec(|f| e1.each(f)))
assert_eq!(~[A], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e1.each(f)))

e1.add(C);
assert_eq!(~[A,C], iter::to_vec(|f| e1.each(f)))
assert_eq!(~[A,C], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e1.each(f)))

e1.add(C);
assert_eq!(~[A,C], iter::to_vec(|f| e1.each(f)))
assert_eq!(~[A,C], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e1.each(f)))

e1.add(B);
assert_eq!(~[A,B,C], iter::to_vec(|f| e1.each(f)))
assert_eq!(~[A,B,C], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e1.each(f)))
}

///////////////////////////////////////////////////////////////////////////
Expand All @@ -236,12 +236,12 @@ mod test {
e2.add(C);

let e_union = e1 | e2;
assert_eq!(~[A,B,C], iter::to_vec(|f| e_union.each(f)))
assert_eq!(~[A,B,C], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e_union.each(f)))

let e_intersection = e1 & e2;
assert_eq!(~[C], iter::to_vec(|f| e_intersection.each(f)))
assert_eq!(~[C], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e_intersection.each(f)))

let e_subtract = e1 - e2;
assert_eq!(~[A], iter::to_vec(|f| e_subtract.each(f)))
assert_eq!(~[A], iter::FromIter::from_iter::<Foo, ~[Foo]>(|f| e_subtract.each(f)))
}
}
32 changes: 14 additions & 18 deletions src/libstd/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,18 @@ pub trait Times {
fn times(&self, it: &fn() -> bool) -> bool;
}

/**
* Transform an internal iterator into an owned vector.
*
* # Example:
*
* ~~~ {.rust}
* let xs = ~[1, 2, 3];
* let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
* assert_eq!(xs, ys);
* ~~~
*/
#[inline(always)]
pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
let mut v = ~[];
for iter |x| { v.push(x) }
v
#[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.each(|x| f(*x)) };
/// assert_eq!(xs, ys);
/// ~~~
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
}

/**
Expand Down Expand Up @@ -262,9 +258,9 @@ mod tests {
use uint;

#[test]
fn test_to_vec() {
fn test_from_iter() {
let xs = ~[1, 2, 3];
let ys = do to_vec |f| { xs.each(|x| f(*x)) };
let ys: ~[int] = do FromIter::from_iter |f| { xs.each(|x| f(*x)) };
assert_eq!(xs, ys);
}

Expand Down
31 changes: 21 additions & 10 deletions src/libstd/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ implementing the `Iterator` trait.

use cmp;
use iter;
use iter::{FromIter, Times};
use num::{Zero, One};
use prelude::*;
use option::{Option, Some, None};
use ops::{Add, Mul};
use cmp::Ord;
use clone::Clone;

/// An interface for dealing with "external iterators". These types of iterators
/// can be resumed at any time as all state is stored internally as opposed to
Expand Down Expand Up @@ -241,19 +245,19 @@ pub trait IteratorUtil<A> {
/// ~~~
fn advance(&mut self, f: &fn(A) -> bool) -> bool;

/// Loops through the entire iterator, accumulating all of the elements into
/// a vector.
/// Loops through the entire iterator, collecting all of the elements into
/// a container implementing `FromIter`.
///
/// # Example
///
/// ~~~ {.rust}
/// use std::iterator::*;
///
/// let a = [1, 2, 3, 4, 5];
/// let b = a.iter().transform(|&x| x).to_vec();
/// let b: ~[int] = a.iter().transform(|&x| x).collect();
/// assert!(a == b);
/// ~~~
fn to_vec(&mut self) -> ~[A];
fn collect<B: FromIter<A>>(&mut self) -> B;

/// Loops through `n` iterations, returning the `n`th element of the
/// iterator.
Expand Down Expand Up @@ -415,8 +419,8 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
}

#[inline(always)]
fn to_vec(&mut self) -> ~[A] {
iter::to_vec::<A>(|f| self.advance(f))
fn collect<B: FromIter<A>>(&mut self) -> B {
FromIter::from_iter::<A, B>(|f| self.advance(f))
}

/// Return the `n`th item yielded by an iterator.
Expand Down Expand Up @@ -870,9 +874,9 @@ mod tests {
use uint;

#[test]
fn test_counter_to_vec() {
fn test_counter_from_iter() {
let mut it = Counter::new(0, 5).take(10);
let xs = iter::to_vec(|f| it.advance(f));
let xs: ~[int] = iter::FromIter::from_iter::<int, ~[int]>(|f| it.advance(f));
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
}

Expand Down Expand Up @@ -903,7 +907,7 @@ mod tests {
fn test_filter_map() {
let mut it = Counter::new(0u, 1u).take(10)
.filter_map(|x: uint| if x.is_even() { Some(x*x) } else { None });
assert_eq!(it.to_vec(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
}

#[test]
Expand Down Expand Up @@ -1062,6 +1066,13 @@ mod tests {
assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
}

#[test]
fn test_collect() {
let a = ~[1, 2, 3, 4, 5];
let b: ~[int] = a.iter().transform(|&x| x).collect();
assert_eq!(a, b);
}

#[test]
fn test_all() {
let v = ~&[1, 2, 3, 4, 5];
Expand Down
5 changes: 3 additions & 2 deletions src/libstd/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Many programming languages have a 'prelude': a particular subset of the
libraries that come with the language. Every program imports the prelude by
default.

For example, it would be annoying to add `use io::println;` to every single
For example, it would be annoying to add `use std::io::println;` to every single
program, and the vast majority of Rust programs will wish to print to standard
output. Therefore, it makes sense to import it into every program.

Expand Down Expand Up @@ -49,7 +49,8 @@ pub use hash::Hash;
pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
pub use old_iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
pub use old_iter::{ExtendedMutableIter};
pub use iter::Times;
pub use iter::{Times, FromIter};
// FIXME: #5898 pub use iterator::{Iterator, IteratorUtil};
pub use num::{Num, NumCast};
pub use num::{Orderable, Signed, Unsigned, Round};
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
Expand Down
10 changes: 10 additions & 0 deletions src/libstd/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use clone::Clone;
use old_iter::BaseIter;
use old_iter;
use iterator::Iterator;
use iter::FromIter;
use kinds::Copy;
use libc;
use old_iter::CopyableIter;
Expand Down Expand Up @@ -2996,6 +2997,15 @@ impl<'self, T> Iterator<&'self mut T> for MutVecIterator<'self, T> {
}
}

impl<T> FromIter<T> for ~[T]{
#[inline(always)]
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
let mut v = ~[];
for iter |x| { v.push(x) }
v
}
}

#[cfg(test)]
mod tests {
use option::{None, Option, Some};
Expand Down