2013-02-26 03:02:53 -06:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
|
|
|
|
|
|
|
The iteration traits and common implementation
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2012-08-27 18:26:35 -05:00
|
|
|
use cmp::{Eq, Ord};
|
2013-01-08 21:37:25 -06:00
|
|
|
use kinds::Copy;
|
|
|
|
use option::{None, Option, Some};
|
2012-12-23 16:41:37 -06:00
|
|
|
use vec;
|
2012-08-27 18:26:35 -05:00
|
|
|
|
2012-08-24 16:45:02 -05:00
|
|
|
/// A function used to initialize the elements of a sequence
|
2013-03-25 15:21:04 -05:00
|
|
|
pub type InitOp<'self,T> = &'self fn(uint) -> T;
|
2012-08-24 16:45:02 -05:00
|
|
|
|
2012-10-01 18:36:15 -05:00
|
|
|
pub trait BaseIter<A> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn each(&self, blk: &fn(v: &A) -> bool);
|
|
|
|
fn size_hint(&self) -> Option<uint>;
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
|
2013-02-07 18:35:18 -06:00
|
|
|
pub trait ReverseIter<A>: BaseIter<A> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn each_reverse(&self, blk: &fn(&A) -> bool);
|
2013-02-07 18:35:18 -06:00
|
|
|
}
|
|
|
|
|
2013-03-13 19:55:42 -05:00
|
|
|
pub trait MutableIter<A>: BaseIter<A> {
|
|
|
|
fn each_mut(&mut self, blk: &fn(&mut A) -> bool);
|
|
|
|
}
|
|
|
|
|
2012-10-01 18:36:15 -05:00
|
|
|
pub trait ExtendedIter<A> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn eachi(&self, blk: &fn(uint, v: &A) -> bool);
|
|
|
|
fn all(&self, blk: &fn(&A) -> bool) -> bool;
|
|
|
|
fn any(&self, blk: &fn(&A) -> bool) -> bool;
|
|
|
|
fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
|
|
|
|
fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
|
|
|
|
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
|
|
|
|
fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
|
2012-08-27 18:26:35 -05:00
|
|
|
}
|
|
|
|
|
2012-10-01 18:36:15 -05:00
|
|
|
pub trait EqIter<A:Eq> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn contains(&self, x: &A) -> bool;
|
|
|
|
fn count(&self, x: &A) -> uint;
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2012-10-01 18:36:15 -05:00
|
|
|
pub trait Times {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn times(&self, it: &fn() -> bool);
|
A new `times` method on numeric types
This method is intended to elegantly subsume two common iteration functions.
The first is `iter::range`, which is used identically to the method introduced
in this commit, but currently works only on uints. The second is a common case
of `{int, i8, uint, etc.}::range`, in the case where the inductive variable is
ignored. Compare the usage of the three:
```
for iter::range(100u) {
// do whatever
}
for int::range(0, 100) |_i| {
// do whatever
}
for 100.times {
// do whatever
}
```
I feel that the latter reads much more nicely than the first two approaches,
and unlike the first two the new method allows the user to ignore the specific
type of the number (ineed, if we're throwing away the inductive variable, who
cares what type it is?). A minor benefit is that this new method will be
somewhat familiar to users of Ruby, from which we borrow the name "times".
2012-07-05 21:12:26 -05:00
|
|
|
}
|
2012-10-01 18:36:15 -05:00
|
|
|
|
|
|
|
pub trait CopyableIter<A:Copy> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
|
|
|
|
fn to_vec(&self) -> ~[A];
|
|
|
|
fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
|
2012-08-27 18:26:35 -05:00
|
|
|
}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
pub trait CopyableOrderedIter<A:Copy + Ord> {
|
2013-03-21 23:20:48 -05:00
|
|
|
fn min(&self) -> A;
|
|
|
|
fn max(&self) -> A;
|
2012-07-11 14:45:54 -05:00
|
|
|
}
|
|
|
|
|
2012-10-31 18:02:16 -05:00
|
|
|
pub trait CopyableNonstrictIter<A:Copy> {
|
|
|
|
// Like "each", but copies out the value. If the receiver is mutated while
|
|
|
|
// iterating over it, the semantics must not be memory-unsafe but are
|
|
|
|
// otherwise undefined.
|
2013-03-21 23:20:48 -05:00
|
|
|
fn each_val(&const self, f: &fn(A) -> bool);
|
2012-10-31 18:02:16 -05:00
|
|
|
}
|
|
|
|
|
2013-02-26 02:56:04 -06:00
|
|
|
// A trait for sequences that can be built by imperatively pushing elements
|
2012-08-24 16:45:02 -05:00
|
|
|
// onto them.
|
2012-10-01 18:36:15 -05:00
|
|
|
pub trait Buildable<A> {
|
2012-08-24 16:45:02 -05:00
|
|
|
/**
|
|
|
|
* Builds a buildable sequence by calling a provided function with
|
|
|
|
* an argument function that pushes an element onto the back of
|
|
|
|
* the sequence.
|
|
|
|
* This version takes an initial size for the sequence.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * size - A hint for an initial size of the sequence
|
2013-01-14 08:45:51 -06:00
|
|
|
* * builder - A function that will construct the sequence. It receives
|
2012-08-24 16:45:02 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the sequence being constructed.
|
|
|
|
*/
|
2013-03-21 23:20:48 -05:00
|
|
|
fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) {
|
2012-09-25 19:39:22 -05:00
|
|
|
let mut i = 0;
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-21 20:43:30 -05:00
|
|
|
if !blk(i, a) { break; }
|
2012-09-25 19:39:22 -05:00
|
|
|
i += 1;
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn all<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-28 19:04:39 -05:00
|
|
|
if !blk(a) { return false; }
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return true;
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn any<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-28 19:04:39 -05:00
|
|
|
if blk(a) { return true; }
|
2012-02-13 00:30:58 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return false;
|
2012-02-13 00:30:58 -06:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
|
|
|
|
prd: &fn(&A) -> bool)
|
|
|
|
-> ~[A] {
|
2012-08-23 12:22:14 -05:00
|
|
|
do vec::build_sized_opt(self.size_hint()) |push| {
|
|
|
|
for self.each |a| {
|
2012-12-17 22:36:12 -06:00
|
|
|
if prd(a) { push(*a); }
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA, op: &fn(&A) -> B) -> ~[B] {
|
2012-08-23 12:22:14 -05:00
|
|
|
do vec::build_sized_opt(self.size_hint()) |push| {
|
|
|
|
for self.each |a| {
|
2012-12-17 22:36:12 -06:00
|
|
|
push(op(a));
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(self: &IA,
|
|
|
|
op: &fn(&A) -> IB)
|
|
|
|
-> ~[B] {
|
2012-08-23 12:22:14 -05:00
|
|
|
do vec::build |push| {
|
|
|
|
for self.each |a| {
|
2012-12-17 22:36:12 -06:00
|
|
|
for op(a).each |&b| {
|
|
|
|
push(b);
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
2012-04-11 23:45:18 -05:00
|
|
|
}
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B, blk: &fn(&B, &A) -> B)
|
|
|
|
-> B {
|
2013-02-15 02:51:28 -06:00
|
|
|
let mut b = b0;
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-28 18:37:14 -05:00
|
|
|
b = blk(&b, a);
|
2012-02-12 04:57:50 -06:00
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
b
|
2012-02-12 04:57:50 -06:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
|
2013-04-12 12:21:46 -05:00
|
|
|
map_to_vec(self, |&x| x)
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-25 19:39:22 -05:00
|
|
|
if *a == *x { return true; }
|
2012-04-11 23:45:18 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return false;
|
2012-02-12 04:44:40 -06:00
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
|
2012-09-25 19:39:22 -05:00
|
|
|
do foldl(self, 0) |count, value| {
|
2012-09-28 18:37:14 -05:00
|
|
|
if *value == *x {
|
|
|
|
*count + 1
|
2012-02-12 04:50:37 -06:00
|
|
|
} else {
|
2012-09-28 18:37:14 -05:00
|
|
|
*count
|
2012-02-12 04:50:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn position<A,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
|
|
|
|
-> Option<uint> {
|
2012-06-25 17:04:00 -05:00
|
|
|
let mut i = 0;
|
2012-06-30 18:19:07 -05:00
|
|
|
for self.each |a| {
|
2012-09-28 23:51:14 -05:00
|
|
|
if f(a) { return Some(i); }
|
2012-06-25 17:04:00 -05:00
|
|
|
i += 1;
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-06-25 17:04:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// note: 'rposition' would only make sense to provide with a bidirectional
|
2013-02-26 02:56:04 -06:00
|
|
|
// iter interface, such as would provide "reach" in addition to "each". As is,
|
2012-06-25 17:04:00 -05:00
|
|
|
// it would have to be implemented with foldr, which is too inefficient.
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn repeat(times: uint, blk: &fn() -> bool) {
|
2012-09-28 23:51:14 -05:00
|
|
|
let mut i = 0;
|
2012-01-31 20:52:20 -06:00
|
|
|
while i < times {
|
2012-07-03 18:46:57 -05:00
|
|
|
if !blk() { break }
|
2012-09-28 23:51:14 -05:00
|
|
|
i += 1;
|
2012-01-31 20:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
|
2012-08-20 14:23:37 -05:00
|
|
|
match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match a {
|
2012-09-28 19:59:01 -05:00
|
|
|
&Some(ref a_) if *a_ < *b => {
|
2013-02-15 02:51:28 -06:00
|
|
|
*(a)
|
2012-02-12 05:04:33 -06:00
|
|
|
}
|
2012-09-28 18:37:14 -05:00
|
|
|
_ => Some(*b)
|
2012-02-12 04:36:40 -06:00
|
|
|
}
|
|
|
|
} {
|
2013-02-15 02:51:28 -06:00
|
|
|
Some(val) => val,
|
2013-02-11 21:26:38 -06:00
|
|
|
None => fail!(~"min called on empty iterator")
|
2012-02-12 04:36:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
|
2012-08-20 14:23:37 -05:00
|
|
|
match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match a {
|
2012-09-28 19:59:01 -05:00
|
|
|
&Some(ref a_) if *a_ > *b => {
|
2013-02-15 02:51:28 -06:00
|
|
|
*(a)
|
2012-02-12 05:04:33 -06:00
|
|
|
}
|
2012-09-28 18:37:14 -05:00
|
|
|
_ => Some(*b)
|
2012-02-12 04:36:40 -06:00
|
|
|
}
|
|
|
|
} {
|
2013-02-15 02:51:28 -06:00
|
|
|
Some(val) => val,
|
2013-02-11 21:26:38 -06:00
|
|
|
None => fail!(~"max called on empty iterator")
|
2012-02-12 04:36:40 -06:00
|
|
|
}
|
|
|
|
}
|
2012-01-31 20:52:20 -06:00
|
|
|
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn find<A:Copy,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
|
|
|
|
-> Option<A> {
|
2012-08-23 12:22:14 -05:00
|
|
|
for self.each |i| {
|
2012-12-17 22:36:12 -06:00
|
|
|
if f(i) { return Some(*i) }
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
|
|
|
|
2012-08-24 16:45:02 -05:00
|
|
|
// Some functions for just building
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds a sequence by calling a provided function with an argument
|
|
|
|
* function that pushes an element to the back of a sequence.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
2013-01-14 08:45:51 -06:00
|
|
|
* * builder - A function that will construct the sequence. It receives
|
2012-08-24 16:45:02 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the sequence being constructed.
|
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
|
2012-12-13 17:55:05 -06:00
|
|
|
Buildable::build_sized(4, builder)
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds a sequence by calling a provided function with an argument
|
2013-02-26 02:56:04 -06:00
|
|
|
* function that pushes an element to the back of the sequence.
|
2012-08-24 16:45:02 -05:00
|
|
|
* This version takes an initial size for the sequence.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * size - An option, maybe containing initial size of the sequence
|
2013-02-26 02:56:04 -06:00
|
|
|
* to reserve.
|
2013-01-14 08:45:51 -06:00
|
|
|
* * builder - A function that will construct the sequence. It receives
|
2012-08-24 16:45:02 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the sequence being constructed.
|
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
|
|
|
|
builder: &fn(push: &fn(A))) -> B {
|
2013-01-04 18:01:26 -06:00
|
|
|
Buildable::build_sized(size.get_or_default(4), builder)
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Functions that combine iteration and building
|
|
|
|
|
2013-03-25 09:22:19 -05:00
|
|
|
/// Applies a function to each element of an iterable and returns the results
|
|
|
|
/// in a sequence built via `BU`. See also `map_to_vec`.
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-07 16:38:38 -06:00
|
|
|
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
|
2012-10-01 18:36:15 -05:00
|
|
|
-> BU {
|
2012-08-24 16:45:02 -05:00
|
|
|
do build_sized_opt(v.size_hint()) |push| {
|
|
|
|
for v.each() |elem| {
|
2012-09-28 20:11:22 -05:00
|
|
|
push(f(elem));
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-02-26 02:56:04 -06:00
|
|
|
* Creates and initializes a generic sequence from a function.
|
2012-08-24 16:45:02 -05:00
|
|
|
*
|
|
|
|
* Creates a generic sequence of size `n_elts` and initializes the elements
|
|
|
|
* to the value returned by the function `op`.
|
|
|
|
*/
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
|
2012-12-13 17:55:05 -06:00
|
|
|
do Buildable::build_sized(n_elts) |push| {
|
2012-08-24 16:45:02 -05:00
|
|
|
let mut i: uint = 0u;
|
|
|
|
while i < n_elts { push(op(i)); i += 1u; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-02-26 02:56:04 -06:00
|
|
|
* Creates and initializes a generic sequence with some elements.
|
2012-08-24 16:45:02 -05:00
|
|
|
*
|
|
|
|
* Creates an immutable vector of size `n_elts` and initializes the elements
|
|
|
|
* to the value `t`.
|
|
|
|
*/
|
2013-01-13 08:37:30 -06:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
|
2012-12-13 17:55:05 -06:00
|
|
|
do Buildable::build_sized(n_elts) |push| {
|
2012-09-28 20:11:22 -05:00
|
|
|
let mut i: uint = 0;
|
|
|
|
while i < n_elts { push(t); i += 1; }
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-26 02:56:04 -06:00
|
|
|
/// Appends two generic sequences.
|
2012-08-24 16:45:02 -05:00
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
|
|
|
|
-> BT {
|
2012-09-27 19:01:28 -05:00
|
|
|
let size_opt = lhs.size_hint().chain_ref(
|
|
|
|
|sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
|
2012-08-24 16:45:02 -05:00
|
|
|
do build_sized_opt(size_opt) |push| {
|
2012-09-19 18:55:01 -05:00
|
|
|
for lhs.each |x| { push(*x); }
|
|
|
|
for rhs.each |x| { push(*x); }
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copies a generic sequence, possibly converting it to a different
|
|
|
|
/// type of sequence.
|
|
|
|
#[inline(always)]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
|
2012-08-24 16:45:02 -05:00
|
|
|
do build_sized_opt(v.size_hint()) |push| {
|
2012-09-19 18:55:01 -05:00
|
|
|
for v.each |x| { push(*x); }
|
2012-08-24 16:45:02 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-10 09:57:52 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to transform an internal iterator into an owned vector.
|
|
|
|
*
|
|
|
|
* # Example:
|
|
|
|
*
|
|
|
|
* ~~~
|
|
|
|
* let v = ~[1, 2, 3];
|
|
|
|
* let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) };
|
|
|
|
* if v != v2 { fail!() }
|
|
|
|
* ~~~
|
|
|
|
*/
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn iter_to_vec<T>(pusher: &fn(it: &fn(T) -> bool)) -> ~[T] {
|
|
|
|
let mut v = ~[];
|
|
|
|
let pushf = |e| {v.push(e); true};
|
|
|
|
pusher(pushf);
|
|
|
|
v
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_iter_to_vec() {
|
|
|
|
let v = ~[1, 2, 3];
|
|
|
|
let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) };
|
|
|
|
if v != v2 { fail!() }
|
|
|
|
}
|