|
8 | 8 | // option. This file may not be copied, modified, or distributed
|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
11 |
| -//! Composable external iterators |
| 11 | +//! Composable external iteration |
12 | 12 | //!
|
13 |
| -//! # The `Iterator` trait |
| 13 | +//! If you've found yourself with a collection of some kind, and needed to |
| 14 | +//! perform an operation on the elements of said collection, you'll quickly run |
| 15 | +//! into 'iterators'. Iterators are heavily used in idiomatic Rust code, so |
| 16 | +//! it's worth becoming familiar with them. |
14 | 17 | //!
|
15 |
| -//! This module defines Rust's core iteration trait. The `Iterator` trait has |
16 |
| -//! one unimplemented method, `next`. All other methods are derived through |
17 |
| -//! default methods to perform operations such as `zip`, `chain`, `enumerate`, |
18 |
| -//! and `fold`. |
| 18 | +//! Before explaining more, let's talk about how this module is structured: |
19 | 19 | //!
|
20 |
| -//! The goal of this module is to unify iteration across all containers in Rust. |
21 |
| -//! An iterator can be considered as a state machine which is used to track |
22 |
| -//! which element will be yielded next. |
| 20 | +//! # Organization |
23 | 21 | //!
|
24 |
| -//! There are various extensions also defined in this module to assist with |
25 |
| -//! various types of iteration, such as the `DoubleEndedIterator` for iterating |
26 |
| -//! in reverse, the `FromIterator` trait for creating a container from an |
27 |
| -//! iterator, and much more. |
| 22 | +//! This module is largely organized by type: |
28 | 23 | //!
|
29 |
| -//! # Rust's `for` loop |
| 24 | +//! * [Traits] are the core portion: these traits define what kind of iterators |
| 25 | +//! exist and what you can do with them. The methods of these traits are worth |
| 26 | +//! putting some extra study time into. |
| 27 | +//! * [Functions] provide some helpful ways to create some basic iterators. |
| 28 | +//! * [Structs] are often the return types of the various methods on this |
| 29 | +//! module's traits. You'll usually want to look at the method that creates |
| 30 | +//! the `struct`, rather than the `struct` itself. For more detail about why, |
| 31 | +//! see '[Implementing Iterator](#implementing-iterator)'. |
30 | 32 | //!
|
31 |
| -//! The special syntax used by rust's `for` loop is based around the |
32 |
| -//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a |
33 |
| -//! syntactical expansion into a `loop`, for example, the `for` loop in this |
34 |
| -//! example is essentially translated to the `loop` below. |
| 33 | +//! [Traits]: #traits |
| 34 | +//! [Functions]: #functions |
| 35 | +//! [Structs]: #structs |
| 36 | +//! |
| 37 | +//! That's it! Let's dig into iterators. |
| 38 | +//! |
| 39 | +//! # Iterator |
| 40 | +//! |
| 41 | +//! The heart and soul of this module is the [`Iterator`] trait. The core of |
| 42 | +//! [`Iterator`] looks like this: |
35 | 43 | //!
|
36 | 44 | //! ```
|
37 |
| -//! let values = vec![1, 2, 3]; |
| 45 | +//! trait Iterator { |
| 46 | +//! type Item; |
| 47 | +//! fn next(&mut self) -> Option<Self::Item>; |
| 48 | +//! } |
| 49 | +//! ``` |
| 50 | +//! |
| 51 | +//! An iterator has a method, [`next()`], which when called, returns an |
| 52 | +//! [`Option`]`<Item>`. [`next()`] will return `Some(Item)` as long as there |
| 53 | +//! are elements, and once they've all been exhausted, will return `None` to |
| 54 | +//! indicate that iteration is finished. Individual iterators may choose to |
| 55 | +//! resume iteration, and so calling [`next()`] again may or may not eventually |
| 56 | +//! start returning `Some(Item)` again at some point. |
| 57 | +//! |
| 58 | +//! [`Iterator`]'s full definition includes a number of other methods as well, |
| 59 | +//! but they are default methods, built on top of [`next()`], and so you get |
| 60 | +//! them for free. |
| 61 | +//! |
| 62 | +//! Iterators are also composable, and it's common to chain them together to do |
| 63 | +//! more complex forms of processing. See the [Adapters](#adapters) section |
| 64 | +//! below for more details. |
| 65 | +//! |
| 66 | +//! [`Iterator`]: trait.Iterator.html |
| 67 | +//! [`next()`]: trait.Iterator.html#tymethod.next |
| 68 | +//! [`Option`]: ../option/enum.Option.html |
| 69 | +//! |
| 70 | +//! # The three forms of iteration |
| 71 | +//! |
| 72 | +//! There are three common methods which can create iterators from a collection: |
| 73 | +//! |
| 74 | +//! * `iter()`, which iterates over `&T`. |
| 75 | +//! * `iter_mut()`, which iterates over `&mut T`. |
| 76 | +//! * `into_iter()`, which iterates over `T`. |
| 77 | +//! |
| 78 | +//! Various things in the standard library may implement one or more of the |
| 79 | +//! three, where appropriate. |
| 80 | +//! |
| 81 | +//! # Implementing Iterator |
| 82 | +//! |
| 83 | +//! Creating an iterator of your own involves two steps: creating a `struct` to |
| 84 | +//! hold the iterator's state, and then `impl`ementing [`Iterator`] for that |
| 85 | +//! `struct`. This is why there are so many `struct`s in this module: there is |
| 86 | +//! one for each iterator and iterator adapter. |
| 87 | +//! |
| 88 | +//! Let's make an iterator named `Counter` which counts from `1` to `5`: |
| 89 | +//! |
| 90 | +//! ``` |
| 91 | +//! // First, the struct: |
| 92 | +//! |
| 93 | +//! /// An iterator which counts from one to five |
| 94 | +//! struct Counter { |
| 95 | +//! count: i32, |
| 96 | +//! } |
| 97 | +//! |
| 98 | +//! // we want our count to start at one, so let's add a new() method to help. |
| 99 | +//! // This isn't strictly necessary, but is convenient. Note that we start |
| 100 | +//! // `count` at zero, we'll see why in `next()`'s implementation below. |
| 101 | +//! impl Counter { |
| 102 | +//! fn new() -> Counter { |
| 103 | +//! Counter { count: 0 } |
| 104 | +//! } |
| 105 | +//! } |
| 106 | +//! |
| 107 | +//! // Then, we implement `Iterator` for our `Counter`: |
| 108 | +//! |
| 109 | +//! impl Iterator for Counter { |
| 110 | +//! // we will be counting with i32 |
| 111 | +//! type Item = i32; |
| 112 | +//! |
| 113 | +//! // next() is the only required method |
| 114 | +//! fn next(&mut self) -> Option<i32> { |
| 115 | +//! // increment our count. This is why we started at zero. |
| 116 | +//! self.count += 1; |
| 117 | +//! |
| 118 | +//! // check to see if we've finished counting or not. |
| 119 | +//! if self.count < 6 { |
| 120 | +//! Some(self.count) |
| 121 | +//! } else { |
| 122 | +//! None |
| 123 | +//! } |
| 124 | +//! } |
| 125 | +//! } |
| 126 | +//! |
| 127 | +//! // And now we can use it! |
| 128 | +//! |
| 129 | +//! let mut counter = Counter::new(); |
| 130 | +//! |
| 131 | +//! let x = counter.next().unwrap(); |
| 132 | +//! println!("{}", x); |
| 133 | +//! |
| 134 | +//! let x = counter.next().unwrap(); |
| 135 | +//! println!("{}", x); |
| 136 | +//! |
| 137 | +//! let x = counter.next().unwrap(); |
| 138 | +//! println!("{}", x); |
| 139 | +//! |
| 140 | +//! let x = counter.next().unwrap(); |
| 141 | +//! println!("{}", x); |
| 142 | +//! |
| 143 | +//! let x = counter.next().unwrap(); |
| 144 | +//! println!("{}", x); |
| 145 | +//! ``` |
| 146 | +//! |
| 147 | +//! This will print `1` through `5`, each on their own line. |
| 148 | +//! |
| 149 | +//! Calling `next()` this way gets repetitive. Rust has a construct which can |
| 150 | +//! call `next()` on your iterator, until it reaches `None`. Let's go over that |
| 151 | +//! next. |
| 152 | +//! |
| 153 | +//! # for Loops and IntoIterator |
| 154 | +//! |
| 155 | +//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic |
| 156 | +//! example of `for`: |
| 157 | +//! |
| 158 | +//! ``` |
| 159 | +//! let values = vec![1, 2, 3, 4, 5]; |
38 | 160 | //!
|
39 | 161 | //! for x in values {
|
40 | 162 | //! println!("{}", x);
|
41 | 163 | //! }
|
| 164 | +//! ``` |
42 | 165 | //!
|
43 |
| -//! // Rough translation of the iteration without a `for` iterator. |
44 |
| -//! # let values = vec![1, 2, 3]; |
45 |
| -//! let mut it = values.into_iter(); |
46 |
| -//! loop { |
47 |
| -//! match it.next() { |
48 |
| -//! Some(x) => println!("{}", x), |
49 |
| -//! None => break, |
50 |
| -//! } |
| 166 | +//! This will print the numbers one through five, each on their own line. But |
| 167 | +//! you'll notice something here: we never called anything on our vector to |
| 168 | +//! produce an iterator. What gives? |
| 169 | +//! |
| 170 | +//! There's a trait in the standard library for converting something into an |
| 171 | +//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter()`], |
| 172 | +//! which converts the thing implementing [`IntoIterator`] into an iterator. |
| 173 | +//! Let's take a look at that `for` loop again, and what the compiler converts |
| 174 | +//! it into: |
| 175 | +//! |
| 176 | +//! [`IntoIterator`]: trait.IntoIterator.html |
| 177 | +//! [`into_iter()`]: trait.IntoIterator.html#tymethod.into_iter |
| 178 | +//! |
| 179 | +//! ``` |
| 180 | +//! let values = vec![1, 2, 3, 4, 5]; |
| 181 | +//! |
| 182 | +//! for x in values { |
| 183 | +//! println!("{}", x); |
| 184 | +//! } |
| 185 | +//! ``` |
| 186 | +//! |
| 187 | +//! Rust de-sugars this into: |
| 188 | +//! |
| 189 | +//! ``` |
| 190 | +//! let values = vec![1, 2, 3, 4, 5]; |
| 191 | +//! { |
| 192 | +//! let result = match values.into_iter() { |
| 193 | +//! mut iter => loop { |
| 194 | +//! match iter.next() { |
| 195 | +//! Some(x) => { println!("{}", x); }, |
| 196 | +//! None => break, |
| 197 | +//! } |
| 198 | +//! }, |
| 199 | +//! }; |
| 200 | +//! result |
| 201 | +//! } |
| 202 | +//! ``` |
| 203 | +//! |
| 204 | +//! First, we call `into_iter()` on the value. Then, we match on the iterator |
| 205 | +//! that returns, calling [`next()`] over and over until we see a `None`. At |
| 206 | +//! that point, we `break` out of the loop, and we're done iterating. |
| 207 | +//! |
| 208 | +//! There's one more subtle bit here: the standard library contains an |
| 209 | +//! interesting implementation of [`IntoIterator`]: |
| 210 | +//! |
| 211 | +//! ```ignore |
| 212 | +//! impl<I> IntoIterator for I where I: Iterator |
| 213 | +//! ``` |
| 214 | +//! |
| 215 | +//! In other words, all [`Iterator`]s implement [`IntoIterator`], by just |
| 216 | +//! returning themselves. This means two things: |
| 217 | +//! |
| 218 | +//! 1. If you're writing an [`Iterator`], you can use it with a `for` loop. |
| 219 | +//! 2. If you're creating a collection, implementing [`IntoIterator`] for it |
| 220 | +//! will allow your collection to be used with the `for` loop. |
| 221 | +//! |
| 222 | +//! # Adapters |
| 223 | +//! |
| 224 | +//! Functions which take an [`Iterator`] and return another [`Iterator`] are |
| 225 | +//! often called 'iterator adapters', as they're a form of the 'adapter |
| 226 | +//! pattern'. |
| 227 | +//! |
| 228 | +//! Common iterator adapters include [`map()`], [`take()`], and [`collect()`]. |
| 229 | +//! For more, see their documentation. |
| 230 | +//! |
| 231 | +//! [`map()`]: trait.Iterator.html#method.map |
| 232 | +//! [`take()`]: trait.Iterator.html#method.take |
| 233 | +//! [`collect()`]: trait.Iterator.html#method.collect |
| 234 | +//! |
| 235 | +//! # Laziness |
| 236 | +//! |
| 237 | +//! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that |
| 238 | +//! just creating an iterator doesn't _do_ a whole lot. Nothing really happens |
| 239 | +//! until you call [`next()`]. This is sometimes a source of confusion when |
| 240 | +//! creating an iterator solely for its side effects. For example, the [`map()`] |
| 241 | +//! method calls a closure on each element it iterates over: |
| 242 | +//! |
| 243 | +//! ``` |
| 244 | +//! let v = vec![1, 2, 3, 4, 5]; |
| 245 | +//! v.iter().map(|x| println!("{}", x)); |
| 246 | +//! ``` |
| 247 | +//! |
| 248 | +//! This will not print any values, as we only created an iterator, rather than |
| 249 | +//! using it. The compiler will warn us about this kind of behavior: |
| 250 | +//! |
| 251 | +//! ```text |
| 252 | +//! warning: unused result which must be used: iterator adaptors are lazy and |
| 253 | +//! do nothing unless consumed |
| 254 | +//! ``` |
| 255 | +//! |
| 256 | +//! The idiomatic way to write a [`map()`] for its side effects is to use a |
| 257 | +//! `for` loop instead: |
| 258 | +//! |
| 259 | +//! ``` |
| 260 | +//! let v = vec![1, 2, 3, 4, 5]; |
| 261 | +//! |
| 262 | +//! for x in &v { |
| 263 | +//! println!("{}", x); |
| 264 | +//! } |
| 265 | +//! ``` |
| 266 | +//! |
| 267 | +//! [`map()`]: trait.Iterator.html#method.map |
| 268 | +//! |
| 269 | +//! The two most common ways to evaluate an iterator are to use a `for` loop |
| 270 | +//! like this, or using the [`collect()`] adapter to produce a new collection. |
| 271 | +//! |
| 272 | +//! [`collect()`]: trait.Iterator.html#method.collect |
| 273 | +//! |
| 274 | +//! # Infinity |
| 275 | +//! |
| 276 | +//! Iterators do not have to be finite. As an example, an open-ended range is |
| 277 | +//! an infinite iterator: |
| 278 | +//! |
| 279 | +//! ``` |
| 280 | +//! let numbers = 0..; |
| 281 | +//! ``` |
| 282 | +//! |
| 283 | +//! It is common to use the [`take()`] iterator adapter to turn an infinite |
| 284 | +//! iterator into a finite one: |
| 285 | +//! |
| 286 | +//! ``` |
| 287 | +//! let numbers = 0..; |
| 288 | +//! let five_numbers = numbers.take(5); |
| 289 | +//! |
| 290 | +//! for number in five_numbers { |
| 291 | +//! println!("{}", number); |
51 | 292 | //! }
|
52 | 293 | //! ```
|
53 | 294 | //!
|
54 |
| -//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be |
55 |
| -//! applied to any iterator over any type. |
| 295 | +//! This will print the numbers `0` through `4`, each on their own line. |
| 296 | +//! |
| 297 | +//! [`take()`]: trait.Iterator.html#method.take |
56 | 298 |
|
57 | 299 | #![stable(feature = "rust1", since = "1.0.0")]
|
58 | 300 |
|
|
0 commit comments