auto merge of #8503 : thestinger/rust/iterator, r=alexcrichton

This commit is contained in:
bors 2013-08-15 18:23:14 -07:00
commit 1ad0cf5841
11 changed files with 23 additions and 237 deletions

View File

@ -112,10 +112,10 @@ iterator object. For example, vector slices several iterators available:
* `iter()` and `rev_iter()`, for immutable references to the elements * `iter()` and `rev_iter()`, for immutable references to the elements
* `mut_iter()` and `mut_rev_iter()`, for mutable references to the elements * `mut_iter()` and `mut_rev_iter()`, for mutable references to the elements
* `consume_iter()` and `consume_rev_iter`, to move the elements out by-value * `move_iter()` and `move_rev_iter`, to move the elements out by-value
A typical mutable container will implement at least `iter()`, `mut_iter()` and A typical mutable container will implement at least `iter()`, `mut_iter()` and
`consume_iter()` along with the reverse variants if it maintains an order. `move_iter()` along with the reverse variants if it maintains an order.
### Freezing ### Freezing
@ -139,9 +139,9 @@ and `&mut`.
## Iterator adaptors ## Iterator adaptors
The `IteratorUtil` trait implements common algorithms as methods extending The `Iterator` trait provides many common algorithms as default methods. For
every `Iterator` implementation. For example, the `fold` method will accumulate example, the `fold` method will accumulate the items yielded by an `Iterator`
the items yielded by an `Iterator` into a single value: into a single value:
~~~ ~~~
let xs = [1, 9, 2, 3, 14, 12]; let xs = [1, 9, 2, 3, 14, 12];
@ -154,14 +154,10 @@ Some adaptors return an adaptor object implementing the `Iterator` trait itself:
~~~ ~~~
let xs = [1, 9, 2, 3, 14, 12]; let xs = [1, 9, 2, 3, 14, 12];
let ys = [5, 2, 1, 8]; let ys = [5, 2, 1, 8];
let sum = xs.iter().chain_(ys.iter()).fold(0, |a, b| a + *b); let sum = xs.iter().chain(ys.iter()).fold(0, |a, b| a + *b);
assert_eq!(sum, 57); assert_eq!(sum, 57);
~~~ ~~~
Note that some adaptors like the `chain_` method above use a trailing
underscore to work around an issue with method resolve. The underscores will be
dropped when they become unnecessary.
## For loops ## For loops
The `for` keyword can be used as sugar for iterating through any iterator: The `for` keyword can be used as sugar for iterating through any iterator:
@ -212,7 +208,7 @@ Iterators offer generic conversion to containers with the `collect` adaptor:
~~~ ~~~
let xs = [0, 1, 1, 2, 3, 5, 8]; let xs = [0, 1, 1, 2, 3, 5, 8];
let ys = xs.rev_iter().skip(1).transform(|&x| x * 2).collect::<~[int]>(); let ys = xs.rev_iter().skip(1).map(|&x| x * 2).collect::<~[int]>();
assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]); assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
~~~ ~~~
@ -307,13 +303,13 @@ for &x in it.invert() {
The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
version of the standard immutable and mutable vector iterators. version of the standard immutable and mutable vector iterators.
The `chain_`, `transform`, `filter`, `filter_map` and `peek` adaptors are The `chain`, `map`, `filter`, `filter_map` and `inspect` adaptors are
`DoubleEndedIterator` implementations if the underlying iterators are. `DoubleEndedIterator` implementations if the underlying iterators are.
~~~ ~~~
let xs = [1, 2, 3, 4]; let xs = [1, 2, 3, 4];
let ys = [5, 6, 7, 8]; let ys = [5, 6, 7, 8];
let mut it = xs.iter().chain_(ys.iter()).transform(|&x| x * 2); let mut it = xs.iter().chain(ys.iter()).map(|&x| x * 2);
printfln!("%?", it.next()); // prints `Some(2)` printfln!("%?", it.next()); // prints `Some(2)`
@ -329,13 +325,13 @@ The `RandomAccessIterator` trait represents an iterator offering random access
to the whole range. The `indexable` method retrieves the number of elements to the whole range. The `indexable` method retrieves the number of elements
accessible with the `idx` method. accessible with the `idx` method.
The `chain_` adaptor is an implementation of `RandomAccessIterator` if the The `chain` adaptor is an implementation of `RandomAccessIterator` if the
underlying iterators are. underlying iterators are.
~~~ ~~~
let xs = [1, 2, 3, 4, 5]; let xs = [1, 2, 3, 4, 5];
let ys = ~[7, 9, 11]; let ys = ~[7, 9, 11];
let mut it = xs.iter().chain_(ys.iter()); let mut it = xs.iter().chain(ys.iter());
printfln!("%?", it.idx(0)); // prints `Some(&1)` printfln!("%?", it.idx(0)); // prints `Some(&1)`
printfln!("%?", it.idx(5)); // prints `Some(&7)` printfln!("%?", it.idx(5)); // prints `Some(&7)`
printfln!("%?", it.idx(7)); // prints `Some(&11)` printfln!("%?", it.idx(7)); // prints `Some(&11)`

View File

@ -782,11 +782,8 @@ mod test_qsort3 {
#[cfg(test)] #[cfg(test)]
mod test_qsort { mod test_qsort {
use sort::*; use sort::*;
use std::vec;
fn check_sort(v1: &mut [int], v2: &mut [int]) { fn check_sort(v1: &mut [int], v2: &mut [int]) {
let len = v1.len(); let len = v1.len();
fn leual(a: &int, b: &int) -> bool { *a <= *b } fn leual(a: &int, b: &int) -> bool { *a <= *b }
@ -835,9 +832,7 @@ mod test_qsort {
let immut_names = names; let immut_names = names;
let pairs = vec::zip_slice(expected, immut_names); for (&a, &b) in expected.iter().zip(immut_names.iter()) {
for p in pairs.iter() {
let (a, b) = *p;
debug!("%d %d", a, b); debug!("%d %d", a, b);
assert_eq!(a, b); assert_eq!(a, b);
} }

View File

@ -1121,7 +1121,6 @@ mod tests {
use std::either; use std::either;
use std::comm::{stream, SharedChan}; use std::comm::{stream, SharedChan};
use std::vec;
use tempfile; use tempfile;
use std::os; use std::os;
@ -1309,14 +1308,8 @@ mod tests {
~"test::parse_ignored_flag", ~"test::parse_ignored_flag",
~"test::sort_tests"]; ~"test::sort_tests"];
let pairs = vec::zip(expected, filtered); for (a, b) in expected.iter().zip(filtered.iter()) {
assert!(*a == b.desc.name.to_str());
for p in pairs.iter() {
match *p {
(ref a, ref b) => {
assert!(*a == b.desc.name.to_str());
}
}
} }
} }

View File

@ -174,6 +174,7 @@ pub trait Iterator<A> {
/// assert!(it.peek().is_none()); /// assert!(it.peek().is_none());
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ~~~ /// ~~~
#[inline]
fn peekable(self) -> Peekable<A, Self> { fn peekable(self) -> Peekable<A, Self> {
Peekable{iter: self, peeked: None} Peekable{iter: self, peeked: None}
} }
@ -931,8 +932,7 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for Map<'self, A, B, T> {
} }
} }
impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B> impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B> for Map<'self, A, B, T> {
for Map<'self, A, B, T> {
#[inline] #[inline]
fn next_back(&mut self) -> Option<B> { fn next_back(&mut self) -> Option<B> {
let next = self.iter.next_back(); let next = self.iter.next_back();
@ -940,8 +940,7 @@ for Map<'self, A, B, T> {
} }
} }
impl<'self, A, B, T: RandomAccessIterator<A>> RandomAccessIterator<B> impl<'self, A, B, T: RandomAccessIterator<A>> RandomAccessIterator<B> for Map<'self, A, B, T> {
for Map<'self, A, B, T> {
#[inline] #[inline]
fn indexable(&self) -> uint { fn indexable(&self) -> uint {
self.iter.indexable() self.iter.indexable()

View File

@ -18,27 +18,21 @@ intrinsic properties of the type. These classifications, often called
They cannot be implemented by user code, but are instead implemented They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply. by the compiler automatically for the types to which they apply.
The 2 kinds are
* Send - owned types and types containing owned types. These types
may be transferred across task boundaries.
* Freeze - types that are deeply immutable.
*/ */
#[allow(missing_doc)]; /// Types able to be transferred across task boundaries.
#[lang="send"] #[lang="send"]
pub trait Send { pub trait Send {
// empty. // empty.
} }
/// Types that are either immutable or have inherited mutability.
#[lang="freeze"] #[lang="freeze"]
pub trait Freeze { pub trait Freeze {
// empty. // empty.
} }
/// Types with a constant size known at compile-time.
#[lang="sized"] #[lang="sized"]
pub trait Sized { pub trait Sized {
// Empty. // Empty.

View File

@ -69,7 +69,7 @@ pub use str::{Str, StrVector, StrSlice, OwnedStr};
pub use from_str::FromStr; pub use from_str::FromStr;
pub use to_bytes::IterBytes; pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume}; pub use to_str::{ToStr, ToStrConsume};
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; pub use tuple::{CopyableTuple, ImmutableTuple};
pub use tuple::{CloneableTuple1, ImmutableTuple1}; pub use tuple::{CloneableTuple1, ImmutableTuple1};
pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5}; pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5};
pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9}; pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9};

View File

@ -47,6 +47,7 @@ pub unsafe fn buf_len<T>(buf: **T) -> uint {
} }
impl<T> Clone for *T { impl<T> Clone for *T {
#[inline]
fn clone(&self) -> *T { fn clone(&self) -> *T {
*self *self
} }

View File

@ -13,9 +13,6 @@
#[allow(missing_doc)]; #[allow(missing_doc)];
use clone::Clone; use clone::Clone;
use vec;
use vec::ImmutableVector;
use iterator::Iterator;
pub use self::inner::*; pub use self::inner::*;
@ -79,55 +76,6 @@ impl<T, U> ImmutableTuple<T, U> for (T, U) {
} }
} }
pub trait ExtendedTupleOps<A,B> {
fn zip(&self) -> ~[(A, B)];
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C];
}
impl<'self,
A:Clone,
B:Clone>
ExtendedTupleOps<A,B> for
(&'self [A], &'self [B]) {
#[inline]
fn zip(&self) -> ~[(A, B)] {
match *self {
(ref a, ref b) => {
vec::zip_slice(*a, *b)
}
}
}
#[inline]
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
a.iter().zip(b.iter()).map(|(aa, bb)| f(aa, bb)).collect()
}
}
}
}
impl<A:Clone, B:Clone> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
#[inline]
fn zip(&self) -> ~[(A, B)] {
match *self {
(ref a, ref b) => {
vec::zip_slice(*a, *b)
}
}
}
#[inline]
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
a.iter().zip(b.iter()).map(|(aa, bb)| f(aa, bb)).collect()
}
}
}
}
// macro for implementing n-ary tuple functions and operations // macro for implementing n-ary tuple functions and operations
macro_rules! tuple_impls { macro_rules! tuple_impls {

View File

@ -390,39 +390,6 @@ pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
(ts, us) (ts, us)
} }
/**
* Convert two vectors to a vector of pairs, by reference. As zip().
*/
pub fn zip_slice<T:Clone,U:Clone>(v: &[T], u: &[U]) -> ~[(T, U)] {
let mut zipped = ~[];
let sz = v.len();
let mut i = 0u;
assert_eq!(sz, u.len());
while i < sz {
zipped.push((v[i].clone(), u[i].clone()));
i += 1u;
}
zipped
}
/**
* Convert two vectors to a vector of pairs.
*
* Returns a vector of tuples, where the i-th tuple contains the
* i-th elements from each of the input vectors.
*/
pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] {
let mut i = v.len();
assert_eq!(i, u.len());
let mut w = with_capacity(i);
while i > 0 {
w.push((v.pop(),u.pop()));
i -= 1;
}
w.reverse();
w
}
/** /**
* Iterate over all permutations of vector `v`. * Iterate over all permutations of vector `v`.
* *
@ -724,12 +691,6 @@ impl<T> Vector<T> for @[T] {
} }
impl<'self, T> Container for &'self [T] { impl<'self, T> Container for &'self [T] {
/// Returns true if a vector contains no elements
#[inline]
fn is_empty(&self) -> bool {
self.as_imm_buf(|_p, len| len == 0u)
}
/// Returns the length of a vector /// Returns the length of a vector
#[inline] #[inline]
fn len(&self) -> uint { fn len(&self) -> uint {
@ -738,12 +699,6 @@ impl<'self, T> Container for &'self [T] {
} }
impl<T> Container for ~[T] { impl<T> Container for ~[T] {
/// Returns true if a vector contains no elements
#[inline]
fn is_empty(&self) -> bool {
self.as_imm_buf(|_p, len| len == 0u)
}
/// Returns the length of a vector /// Returns the length of a vector
#[inline] #[inline]
fn len(&self) -> uint { fn len(&self) -> uint {
@ -2865,14 +2820,7 @@ mod tests {
#[test] #[test]
fn test_zip_unzip() { fn test_zip_unzip() {
let v1 = ~[1, 2, 3]; let z1 = ~[(1, 4), (2, 5), (3, 6)];
let v2 = ~[4, 5, 6];
let z1 = zip(v1, v2);
assert_eq!((1, 4), z1[0]);
assert_eq!((2, 5), z1[1]);
assert_eq!((3, 6), z1[2]);
let (left, right) = unzip(z1); let (left, right) = unzip(z1);

View File

@ -1,44 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// In this case, the code should compile but
// the assert should fail at runtime
// error-pattern:assertion failed
extern mod extra;
use std::vec::{same_length, zip};
fn enum_chars(start: u8, end: u8) -> ~[char] {
assert!(start < end);
let mut i = start;
let mut r = ~[];
while i <= end { r.push(i as char); i += 1 as u8; }
return r;
}
fn enum_uints(start: uint, end: uint) -> ~[uint] {
assert!(start < end);
let mut i = start;
let mut r = ~[];
while i <= end { r.push(i); i += 1; }
return r;
}
fn main() {
let a = 'a' as u8;
let j = 'j' as u8;
let k = 1;
let l = 9;
let chars = enum_chars(a, j);
let ints = enum_uints(k, l);
assert!(same_length(chars, ints));
let ps = zip(chars, ints);
fail!("the impossible happened");
}

View File

@ -1,44 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// In this case, the code should compile and should
// succeed at runtime
use std::vec;
fn enum_chars(start: u8, end: u8) -> ~[char] {
assert!(start < end);
let mut i = start;
let mut r = ~[];
while i <= end { r.push(i as char); i += 1u as u8; }
return r;
}
fn enum_uints(start: uint, end: uint) -> ~[uint] {
assert!(start < end);
let mut i = start;
let mut r = ~[];
while i <= end { r.push(i); i += 1u; }
return r;
}
pub fn main() {
let a = 'a' as u8;
let j = 'j' as u8;
let k = 1u;
let l = 10u;
let chars = enum_chars(a, j);
let ints = enum_uints(k, l);
let ps = vec::zip(chars, ints);
assert_eq!(ps.head(), &('a', 1u));
assert_eq!(ps.last(), &(j as char, 10u));
}