diff --git a/doc/tutorial-container.md b/doc/tutorial-container.md
index 5ed61d693014..2146b76a4afb 100644
--- a/doc/tutorial-container.md
+++ b/doc/tutorial-container.md
@@ -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> FromIterator 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) { (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) {
+ (self.remaining, Some(self.remaining))
+ }
+}
+
+impl Iterator for ZeroStream {
+ fn next(&mut self) -> Option {
+ 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.
diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs
index dc65ef36b67e..f1637ae96a20 100644
--- a/src/libextra/bitv.rs
+++ b/src/libextra/bitv.rs
@@ -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 {
@@ -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 {
@@ -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 } }
}
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index db534cca971a..ea49144b7716 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -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};
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 89c4b39c4293..4ab93da8c098 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -760,6 +760,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
lifetime: cast::transmute(p)}
}
}
+
#[inline]
fn rev_iter(self) -> VecRevIterator<'self, T> {
self.iter().invert()
@@ -2211,7 +2212,6 @@ impl> FromIterator for ~[A] {
}
}
-
#[cfg(test)]
mod tests {
use option::{None, Option, Some};
diff --git a/src/test/run-pass/rcvr-borrowed-to-slice.rs b/src/test/run-pass/rcvr-borrowed-to-slice.rs
index b62475ded54f..3df60762dea0 100644
--- a/src/test/run-pass/rcvr-borrowed-to-slice.rs
+++ b/src/test/run-pass/rcvr-borrowed-to-slice.rs
@@ -11,19 +11,17 @@
use std::vec;
trait sum {
- fn sum(self) -> int;
+ fn sum_(self) -> int;
}
// Note: impl on a slice
impl<'self> sum for &'self [int] {
- fn sum(self) -> int {
- let mut sum = 0;
- for self.iter().advance |e| { sum += *e; }
- return sum;
+ fn sum_(self) -> int {
+ self.iter().fold(0, |a, &b| a + b)
}
}
-fn call_sum(x: &[int]) -> int { x.sum() }
+fn call_sum(x: &[int]) -> int { x.sum_() }
pub fn main() {
let x = ~[1, 2, 3];
@@ -32,12 +30,12 @@ pub fn main() {
assert_eq!(y, 6);
let mut x = ~[1, 2, 3];
- let y = x.sum();
+ let y = x.sum_();
debug!("y==%d", y);
assert_eq!(y, 6);
let x = ~[1, 2, 3];
- let y = x.sum();
+ let y = x.sum_();
debug!("y==%d", y);
assert_eq!(y, 6);
}