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
|
* `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)`
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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.
|
||||||
|
@ -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};
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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