Skip to content

extend the iterator tutorial + fix zero-size element vec iterators #7736

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

Merged
merged 3 commits into from
Jul 12, 2013
Merged
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
101 changes: 101 additions & 0 deletions doc/tutorial-container.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,104 @@ println(fmt!("last: %?", it.next()));
// the iterator is now fully consumed
assert!(it.next().is_none());
~~~

## Conversion

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]>();
assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
~~~

The method requires a type hint for the container type, if the surrounding code
does not provide sufficient information.

Containers can provide conversion from iterators through `collect` by
implementing the `FromIterator` trait. For example, the implementation for
vectors is as follows:

~~~
impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
pub fn from_iterator(iterator: &mut T) -> ~[A] {
let (lower, _) = iterator.size_hint();
let mut xs = with_capacity(lower);
for iterator.advance |x| {
xs.push(x);
}
xs
}
}
~~~

### Size hints

The `Iterator` trait provides a `size_hint` default method, returning a lower
bound and optionally on upper bound on the length of the iterator:

~~~
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
~~~

The vector implementation of `FromIterator` from above uses the lower bound
to pre-allocate enough space to hold the minimum number of elements the
iterator will yield.

The default implementation is always correct, but it should be overridden if
the iterator can provide better information.

The `ZeroStream` from earlier can provide an exact lower and upper bound:

~~~
/// A stream of N zeroes
struct ZeroStream {
priv remaining: uint
}

impl ZeroStream {
fn new(n: uint) -> ZeroStream {
ZeroStream { remaining: n }
}

fn size_hint(&self) -> (uint, Option<uint>) {
(self.remaining, Some(self.remaining))
}
}

impl Iterator<int> for ZeroStream {
fn next(&mut self) -> Option<int> {
if self.remaining == 0 {
None
} else {
self.remaining -= 1;
Some(0)
}
}
}
~~~

## Double-ended iterators

The `DoubleEndedIterator` trait represents an iterator able to yield elements
from either end of a range. It inherits from the `Iterator` trait and extends
it with the `next_back` function.

A `DoubleEndedIterator` can be flipped with the `invert` adaptor, returning
another `DoubleEndedIterator` with `next` and `next_back` exchanged.

~~~
let xs = [1, 2, 3, 4, 5, 6];
let mut it = xs.iter();
println(fmt!("%?", it.next())); // prints `Some(&1)`
println(fmt!("%?", it.next())); // prints `Some(&2)`
println(fmt!("%?", it.next_back())); // prints `Some(&6)`

// prints `5`, `4` and `3`
for it.invert().advance |&x| {
println(fmt!("%?", x))
}
~~~

The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
version of the standard immutable and mutable vector iterators.
8 changes: 4 additions & 4 deletions src/libextra/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl SmallBitv {
}

#[inline]
pub fn invert(&mut self) { self.bits = !self.bits; }
pub fn negate(&mut self) { self.bits = !self.bits; }
}

struct BigBitv {
Expand Down Expand Up @@ -160,7 +160,7 @@ impl BigBitv {
}

#[inline]
pub fn invert(&mut self) { for self.each_storage |w| { *w = !*w } }
pub fn negate(&mut self) { for self.each_storage |w| { *w = !*w } }

#[inline]
pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
Expand Down Expand Up @@ -366,9 +366,9 @@ impl Bitv {

/// Invert all bits
#[inline]
pub fn invert(&mut self) {
pub fn negate(&mut self) {
match self.rep {
Small(ref mut b) => b.invert(),
Small(ref mut b) => b.negate(),
Big(ref mut s) => for s.each_storage() |w| { *w = !*w } }
}

Expand Down
2 changes: 1 addition & 1 deletion src/libextra/flatpipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ pub mod flatteners {
T: Decodable<D>>(
buf: &[u8])
-> T {
let buf = vec::to_owned(buf);
let buf = buf.to_owned();
let buf_reader = @BufReader::new(buf);
let reader = buf_reader as @Reader;
let mut deser: D = FromReader::from_reader(reader);
Expand Down
2 changes: 1 addition & 1 deletion src/libextra/getopts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
}
i += 1;
}
return Ok(Matches {opts: vec::to_owned(opts),
return Ok(Matches {opts: opts.to_owned(),
vals: vals,
free: free});
}
Expand Down
2 changes: 1 addition & 1 deletion src/libextra/md4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn md4(msg: &[u8]) -> Quad {
let orig_len: u64 = (msg.len() * 8u) as u64;

// pad message
let mut msg = vec::append(vec::to_owned(msg), [0x80u8]);
let mut msg = vec::append(msg.to_owned(), [0x80u8]);
let mut bitlen = orig_len + 8u64;
while (bitlen + 64u64) % 512u64 > 0u64 {
msg.push(0u8);
Expand Down
2 changes: 1 addition & 1 deletion src/libextra/num/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ impl BigUint {
/// Creates and initializes an BigUint.

pub fn from_slice(slice: &[BigDigit]) -> BigUint {
return BigUint::new(vec::to_owned(slice));
return BigUint::new(slice.to_owned());
}

/// Creates and initializes an BigUint.
Expand Down
7 changes: 3 additions & 4 deletions src/libextra/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use sort;
use std::cmp;
use std::io;
use std::num;
use std::vec;

// NB: this can probably be rewritten in terms of num::Num
// to be less f64-specific.
Expand Down Expand Up @@ -200,13 +199,13 @@ impl<'self> Stats for &'self [f64] {
}

fn percentile(self, pct: f64) -> f64 {
let mut tmp = vec::to_owned(self);
let mut tmp = self.to_owned();
sort::tim_sort(tmp);
percentile_of_sorted(tmp, pct)
}

fn quartiles(self) -> (f64,f64,f64) {
let mut tmp = vec::to_owned(self);
let mut tmp = self.to_owned();
sort::tim_sort(tmp);
let a = percentile_of_sorted(tmp, 25.0);
let b = percentile_of_sorted(tmp, 50.0);
Expand Down Expand Up @@ -251,7 +250,7 @@ priv fn percentile_of_sorted(sorted_samples: &[f64],
///
/// See: http://en.wikipedia.org/wiki/Winsorising
pub fn winsorize(samples: &mut [f64], pct: f64) {
let mut tmp = vec::to_owned(samples);
let mut tmp = samples.to_owned();
sort::tim_sort(tmp);
let lo = percentile_of_sorted(tmp, pct);
let hi = percentile_of_sorted(tmp, 100.0-pct);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
let item_doc = lookup_item(id, cdata.data);
let path = {
let item_path = item_path(item_doc);
vec::to_owned(item_path.init())
item_path.init().to_owned()
};
match decode_inlined_item(cdata, tcx, copy path, item_doc) {
Some(ref ii) => csearch::found((/*bad*/copy *ii)),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {

let writer_bytes: &mut ~[u8] = wr.bytes;

vec::to_owned(metadata_encoding_version) +
metadata_encoding_version.to_owned() +
flate::deflate_bytes(*writer_bytes)
}

Expand Down
22 changes: 11 additions & 11 deletions src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
match cx.tcx.def_map.find(&pat_id) {
Some(&def_variant(_, id)) => {
if variant(id) == *ctor_id {
Some(vec::to_owned(r.tail()))
Some(r.tail().to_owned())
} else {
None
}
Expand Down Expand Up @@ -522,7 +522,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
_ => fail!("type error")
};
if match_ {
Some(vec::to_owned(r.tail()))
Some(r.tail().to_owned())
} else {
None
}
Expand Down Expand Up @@ -569,7 +569,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
_ => fail!("type error")
};
if match_ {
Some(vec::to_owned(r.tail()))
Some(r.tail().to_owned())
} else {
None
}
Expand All @@ -579,7 +579,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
Some(args) => args,
None => vec::from_elem(arity, wild())
};
Some(vec::append(args, vec::to_owned(r.tail())))
Some(vec::append(args, r.tail()))
}
def_variant(_, _) => None,

Expand All @@ -591,7 +591,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
Some(args) => new_args = args,
None => new_args = vec::from_elem(arity, wild())
}
Some(vec::append(new_args, vec::to_owned(r.tail())))
Some(vec::append(new_args, r.tail()))
}
_ => None
}
Expand All @@ -609,7 +609,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
_ => wild()
}
});
Some(vec::append(args, vec::to_owned(r.tail())))
Some(vec::append(args, r.tail()))
} else {
None
}
Expand Down Expand Up @@ -640,7 +640,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
_ => wild()
}
}).collect();
Some(vec::append(args, vec::to_owned(r.tail())))
Some(vec::append(args, r.tail()))
}
}
}
Expand Down Expand Up @@ -676,14 +676,14 @@ pub fn specialize(cx: &MatchCheckCtxt,
single => true,
_ => fail!("type error")
};
if match_ { Some(vec::to_owned(r.tail())) } else { None }
if match_ { Some(r.tail().to_owned()) } else { None }
}
pat_range(lo, hi) => {
let (c_lo, c_hi) = match *ctor_id {
val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)),
range(ref lo, ref hi) =>
((/*bad*/copy *lo), (/*bad*/copy *hi)),
single => return Some(vec::to_owned(r.tail())),
single => return Some(r.tail().to_owned()),
_ => fail!("type error")
};
let v_lo = eval_const_expr(cx.tcx, lo);
Expand All @@ -693,7 +693,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
let m2 = compare_const_vals(&c_hi, &v_hi);
match (m1, m2) {
(Some(val1), Some(val2)) if val1 >= 0 && val2 <= 0 => {
Some(vec::to_owned(r.tail()))
Some(r.tail().to_owned())
},
(Some(_), Some(_)) => None,
_ => {
Expand Down Expand Up @@ -734,7 +734,7 @@ pub fn specialize(cx: &MatchCheckCtxt,
}

pub fn default(cx: &MatchCheckCtxt, r: &[@pat]) -> Option<~[@pat]> {
if is_wild(cx, r[0]) { Some(vec::to_owned(r.tail())) }
if is_wild(cx, r[0]) { Some(r.tail().to_owned()) }
else { None }
}

Expand Down
3 changes: 1 addition & 2 deletions src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
use std::container::Map;
use std::libc::c_ulonglong;
use std::option::{Option, Some, None};
use std::vec;

use lib::llvm::{ValueRef, True, IntEQ, IntNE};
use middle::trans::_match;
Expand Down Expand Up @@ -219,7 +218,7 @@ fn mk_struct(cx: &mut CrateContext, tys: &[ty::t], packed: bool) -> Struct {
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
packed: packed,
fields: vec::to_owned(tys)
fields: tys.to_owned(),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3782,7 +3782,7 @@ pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
}

ast_map::node_variant(ref variant, _, path) => {
vec::append_one(vec::to_owned(path.init()),
vec::append_one(path.init().to_owned(),
ast_map::path_name((*variant).node.name))
}

Expand Down
5 changes: 3 additions & 2 deletions src/libstd/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Great
pub use char::Char;
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use iter::{Times};
pub use iterator::{Iterator, IteratorUtil, OrdIterator};
pub use iter::Times;
pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
pub use iterator::OrdIterator;
pub use num::{Num, NumCast};
pub use num::{Orderable, Signed, Unsigned, Round};
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ impl<R: Rng> RngUtil for R {

/// Shuffle a vec
fn shuffle<T:Copy>(&mut self, values: &[T]) -> ~[T] {
let mut m = vec::to_owned(values);
let mut m = values.to_owned();
self.shuffle_mut(m);
m
}
Expand Down
Loading