mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 15:12:56 +00:00
auto merge of #8503 : thestinger/rust/iterator, r=alexcrichton
This commit is contained in:
commit
1ad0cf5841
@ -112,10 +112,10 @@ iterator object. For example, vector slices several iterators available:
|
||||
|
||||
* `iter()` and `rev_iter()`, for immutable 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
|
||||
`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
|
||||
|
||||
@ -139,9 +139,9 @@ and `&mut`.
|
||||
|
||||
## Iterator adaptors
|
||||
|
||||
The `IteratorUtil` trait implements common algorithms as methods extending
|
||||
every `Iterator` implementation. For example, the `fold` method will accumulate
|
||||
the items yielded by an `Iterator` into a single value:
|
||||
The `Iterator` trait provides many common algorithms as default methods. For
|
||||
example, the `fold` method will accumulate the items yielded by an `Iterator`
|
||||
into a single value:
|
||||
|
||||
~~~
|
||||
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 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);
|
||||
~~~
|
||||
|
||||
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
|
||||
|
||||
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 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]);
|
||||
~~~
|
||||
|
||||
@ -307,13 +303,13 @@ for &x in it.invert() {
|
||||
The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
|
||||
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.
|
||||
|
||||
~~~
|
||||
let xs = [1, 2, 3, 4];
|
||||
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)`
|
||||
|
||||
@ -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
|
||||
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.
|
||||
|
||||
~~~
|
||||
let xs = [1, 2, 3, 4, 5];
|
||||
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(5)); // prints `Some(&7)`
|
||||
printfln!("%?", it.idx(7)); // prints `Some(&11)`
|
||||
|
@ -782,11 +782,8 @@ mod test_qsort3 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_qsort {
|
||||
|
||||
use sort::*;
|
||||
|
||||
use std::vec;
|
||||
|
||||
fn check_sort(v1: &mut [int], v2: &mut [int]) {
|
||||
let len = v1.len();
|
||||
fn leual(a: &int, b: &int) -> bool { *a <= *b }
|
||||
@ -835,9 +832,7 @@ mod test_qsort {
|
||||
|
||||
let immut_names = names;
|
||||
|
||||
let pairs = vec::zip_slice(expected, immut_names);
|
||||
for p in pairs.iter() {
|
||||
let (a, b) = *p;
|
||||
for (&a, &b) in expected.iter().zip(immut_names.iter()) {
|
||||
debug!("%d %d", a, b);
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
@ -1121,7 +1121,6 @@ mod tests {
|
||||
|
||||
use std::either;
|
||||
use std::comm::{stream, SharedChan};
|
||||
use std::vec;
|
||||
use tempfile;
|
||||
use std::os;
|
||||
|
||||
@ -1309,16 +1308,10 @@ mod tests {
|
||||
~"test::parse_ignored_flag",
|
||||
~"test::sort_tests"];
|
||||
|
||||
let pairs = vec::zip(expected, filtered);
|
||||
|
||||
for p in pairs.iter() {
|
||||
match *p {
|
||||
(ref a, ref b) => {
|
||||
for (a, b) in expected.iter().zip(filtered.iter()) {
|
||||
assert!(*a == b.desc.name.to_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_metricmap_compare() {
|
||||
|
@ -174,6 +174,7 @@ pub trait Iterator<A> {
|
||||
/// assert!(it.peek().is_none());
|
||||
/// assert!(it.next().is_none());
|
||||
/// ~~~
|
||||
#[inline]
|
||||
fn peekable(self) -> Peekable<A, Self> {
|
||||
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>
|
||||
for Map<'self, A, B, T> {
|
||||
impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B> for Map<'self, A, B, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<B> {
|
||||
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>
|
||||
for Map<'self, A, B, T> {
|
||||
impl<'self, A, B, T: RandomAccessIterator<A>> RandomAccessIterator<B> for Map<'self, A, B, T> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint {
|
||||
self.iter.indexable()
|
||||
|
@ -18,27 +18,21 @@ intrinsic properties of the type. These classifications, often called
|
||||
They cannot be implemented by user code, but are instead implemented
|
||||
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"]
|
||||
pub trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
/// Types that are either immutable or have inherited mutability.
|
||||
#[lang="freeze"]
|
||||
pub trait Freeze {
|
||||
// empty.
|
||||
}
|
||||
|
||||
/// Types with a constant size known at compile-time.
|
||||
#[lang="sized"]
|
||||
pub trait Sized {
|
||||
// Empty.
|
||||
|
@ -69,7 +69,7 @@ pub use str::{Str, StrVector, StrSlice, OwnedStr};
|
||||
pub use from_str::FromStr;
|
||||
pub use to_bytes::IterBytes;
|
||||
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::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5};
|
||||
pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9};
|
||||
|
@ -47,6 +47,7 @@ pub unsafe fn buf_len<T>(buf: **T) -> uint {
|
||||
}
|
||||
|
||||
impl<T> Clone for *T {
|
||||
#[inline]
|
||||
fn clone(&self) -> *T {
|
||||
*self
|
||||
}
|
||||
|
@ -13,9 +13,6 @@
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use clone::Clone;
|
||||
use vec;
|
||||
use vec::ImmutableVector;
|
||||
use iterator::Iterator;
|
||||
|
||||
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_rules! tuple_impls {
|
||||
|
@ -390,39 +390,6 @@ pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
|
||||
(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`.
|
||||
*
|
||||
@ -724,12 +691,6 @@ impl<T> Vector<T> for @[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
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
@ -738,12 +699,6 @@ impl<'self, T> Container for &'self [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
|
||||
#[inline]
|
||||
fn len(&self) -> uint {
|
||||
@ -2865,14 +2820,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_zip_unzip() {
|
||||
let v1 = ~[1, 2, 3];
|
||||
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 z1 = ~[(1, 4), (2, 5), (3, 6)];
|
||||
|
||||
let (left, right) = unzip(z1);
|
||||
|
||||
|
@ -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");
|
||||
}
|
@ -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));
|
||||
}
|
Loading…
Reference in New Issue
Block a user