Skip to content

Commit 2b96408

Browse files
committed
extend the iterator tutorial
documents conversion, size hints and double-ended iterators and adds more of the traits to the prelude
1 parent 07183ea commit 2b96408

File tree

5 files changed

+115
-15
lines changed

5 files changed

+115
-15
lines changed

doc/tutorial-container.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,104 @@ println(fmt!("last: %?", it.next()));
205205
// the iterator is now fully consumed
206206
assert!(it.next().is_none());
207207
~~~
208+
209+
## Conversion
210+
211+
Iterators offer generic conversion to containers with the `collect` adaptor:
212+
213+
~~~
214+
let xs = [0, 1, 1, 2, 3, 5, 8];
215+
let ys = xs.rev_iter().skip(1).transform(|&x| x * 2).collect::<~[int]>();
216+
assert_eq!(ys, ~[10, 6, 4, 2, 2, 0]);
217+
~~~
218+
219+
The method requires a type hint for the container type, if the surrounding code
220+
does not provide sufficient information.
221+
222+
Containers can provide conversion from iterators through `collect` by
223+
implementing the `FromIterator` trait. For example, the implementation for
224+
vectors is as follows:
225+
226+
~~~
227+
impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
228+
pub fn from_iterator(iterator: &mut T) -> ~[A] {
229+
let (lower, _) = iterator.size_hint();
230+
let mut xs = with_capacity(lower);
231+
for iterator.advance |x| {
232+
xs.push(x);
233+
}
234+
xs
235+
}
236+
}
237+
~~~
238+
239+
### Size hints
240+
241+
The `Iterator` trait provides a `size_hint` default method, returning a lower
242+
bound and optionally on upper bound on the length of the iterator:
243+
244+
~~~
245+
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
246+
~~~
247+
248+
The vector implementation of `FromIterator` from above uses the lower bound
249+
to pre-allocate enough space to hold the minimum number of elements the
250+
iterator will yield.
251+
252+
The default implementation is always correct, but it should be overridden if
253+
the iterator can provide better information.
254+
255+
The `ZeroStream` from earlier can provide an exact lower and upper bound:
256+
257+
~~~
258+
/// A stream of N zeroes
259+
struct ZeroStream {
260+
priv remaining: uint
261+
}
262+
263+
impl ZeroStream {
264+
fn new(n: uint) -> ZeroStream {
265+
ZeroStream { remaining: n }
266+
}
267+
268+
fn size_hint(&self) -> (uint, Option<uint>) {
269+
(self.remaining, Some(self.remaining))
270+
}
271+
}
272+
273+
impl Iterator<int> for ZeroStream {
274+
fn next(&mut self) -> Option<int> {
275+
if self.remaining == 0 {
276+
None
277+
} else {
278+
self.remaining -= 1;
279+
Some(0)
280+
}
281+
}
282+
}
283+
~~~
284+
285+
## Double-ended iterators
286+
287+
The `DoubleEndedIterator` trait represents an iterator able to yield elements
288+
from either end of a range. It inherits from the `Iterator` trait and extends
289+
it with the `next_back` function.
290+
291+
A `DoubleEndedIterator` can be flipped with the `invert` adaptor, returning
292+
another `DoubleEndedIterator` with `next` and `next_back` exchanged.
293+
294+
~~~
295+
let xs = [1, 2, 3, 4, 5, 6];
296+
let mut it = xs.iter();
297+
println(fmt!("%?", it.next())); // prints `Some(&1)`
298+
println(fmt!("%?", it.next())); // prints `Some(&2)`
299+
println(fmt!("%?", it.next_back())); // prints `Some(&6)`
300+
301+
// prints `5`, `4` and `3`
302+
for it.invert().advance |&x| {
303+
println(fmt!("%?", x))
304+
}
305+
~~~
306+
307+
The `rev_iter` and `mut_rev_iter` methods on vectors just return an inverted
308+
version of the standard immutable and mutable vector iterators.

src/libextra/bitv.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl SmallBitv {
104104
}
105105

106106
#[inline]
107-
pub fn invert(&mut self) { self.bits = !self.bits; }
107+
pub fn negate(&mut self) { self.bits = !self.bits; }
108108
}
109109

110110
struct BigBitv {
@@ -160,7 +160,7 @@ impl BigBitv {
160160
}
161161

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

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

367367
/// Invert all bits
368368
#[inline]
369-
pub fn invert(&mut self) {
369+
pub fn negate(&mut self) {
370370
match self.rep {
371-
Small(ref mut b) => b.invert(),
371+
Small(ref mut b) => b.negate(),
372372
Big(ref mut s) => for s.each_storage() |w| { *w = !*w } }
373373
}
374374

src/libstd/prelude.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Great
4747
pub use char::Char;
4848
pub use container::{Container, Mutable, Map, Set};
4949
pub use hash::Hash;
50-
pub use iter::{Times};
51-
pub use iterator::{Iterator, IteratorUtil, OrdIterator};
50+
pub use iter::Times;
51+
pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
52+
pub use iterator::OrdIterator;
5253
pub use num::{Num, NumCast};
5354
pub use num::{Orderable, Signed, Unsigned, Round};
5455
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};

src/libstd/vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
760760
lifetime: cast::transmute(p)}
761761
}
762762
}
763+
763764
#[inline]
764765
fn rev_iter(self) -> VecRevIterator<'self, T> {
765766
self.iter().invert()
@@ -2211,7 +2212,6 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
22112212
}
22122213
}
22132214

2214-
22152215
#[cfg(test)]
22162216
mod tests {
22172217
use option::{None, Option, Some};

src/test/run-pass/rcvr-borrowed-to-slice.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,17 @@
1111
use std::vec;
1212

1313
trait sum {
14-
fn sum(self) -> int;
14+
fn sum_(self) -> int;
1515
}
1616

1717
// Note: impl on a slice
1818
impl<'self> sum for &'self [int] {
19-
fn sum(self) -> int {
20-
let mut sum = 0;
21-
for self.iter().advance |e| { sum += *e; }
22-
return sum;
19+
fn sum_(self) -> int {
20+
self.iter().fold(0, |a, &b| a + b)
2321
}
2422
}
2523

26-
fn call_sum(x: &[int]) -> int { x.sum() }
24+
fn call_sum(x: &[int]) -> int { x.sum_() }
2725

2826
pub fn main() {
2927
let x = ~[1, 2, 3];
@@ -32,12 +30,12 @@ pub fn main() {
3230
assert_eq!(y, 6);
3331

3432
let mut x = ~[1, 2, 3];
35-
let y = x.sum();
33+
let y = x.sum_();
3634
debug!("y==%d", y);
3735
assert_eq!(y, 6);
3836

3937
let x = ~[1, 2, 3];
40-
let y = x.sum();
38+
let y = x.sum_();
4139
debug!("y==%d", y);
4240
assert_eq!(y, 6);
4341
}

0 commit comments

Comments
 (0)