]> git.proxmox.com Git - rustc.git/blame - src/doc/book/iterators.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / doc / book / iterators.md
CommitLineData
1a4d82fc
JJ
1% Iterators
2
3Let's talk about loops.
4
5Remember Rust's `for` loop? Here's an example:
6
85aaf69f
SL
7```rust
8for x in 0..10 {
1a4d82fc
JJ
9 println!("{}", x);
10}
11```
12
85aaf69f
SL
13Now that you know more Rust, we can talk in detail about how this works.
14Ranges (the `0..10`) are 'iterators'. An iterator is something that we can
1a4d82fc
JJ
15call the `.next()` method on repeatedly, and it gives us a sequence of things.
16
54a0048b
SL
17(By the way, a range with two dots like `0..10` is inclusive on the left (so it
18starts at 0) and exclusive on the right (so it ends at 9). A mathematician
19would write "[0, 10)". To get a range that goes all the way up to 10 you can
20write `0...10`.)
21
1a4d82fc
JJ
22Like this:
23
85aaf69f
SL
24```rust
25let mut range = 0..10;
1a4d82fc
JJ
26
27loop {
28 match range.next() {
29 Some(x) => {
30 println!("{}", x);
31 },
32 None => { break }
33 }
34}
35```
36
85aaf69f
SL
37We make a mutable binding to the range, which is our iterator. We then `loop`,
38with an inner `match`. This `match` is used on the result of `range.next()`,
39which gives us a reference to the next value of the iterator. `next` returns an
40`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and
41`None` once we run out. If we get `Some(i32)`, we print it out, and if we get
42`None`, we `break` out of the loop.
1a4d82fc
JJ
43
44This code sample is basically the same as our `for` loop version. The `for`
9cc50fc6 45loop is a handy way to write this `loop`/`match`/`break` construct.
1a4d82fc
JJ
46
47`for` loops aren't the only thing that uses iterators, however. Writing your
48own iterator involves implementing the `Iterator` trait. While doing that is
49outside of the scope of this guide, Rust provides a number of useful iterators
b039eaaf 50to accomplish various tasks. But first, a few notes about limitations of ranges.
1a4d82fc 51
b039eaaf
SL
52Ranges are very primitive, and we often can use better alternatives. Consider the
53following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s
54suppose you needed to iterate over the contents of a vector. You may be tempted
55to write this:
1a4d82fc 56
85aaf69f
SL
57```rust
58let nums = vec![1, 2, 3];
1a4d82fc 59
85aaf69f 60for i in 0..nums.len() {
1a4d82fc
JJ
61 println!("{}", nums[i]);
62}
63```
64
c34b1796
AL
65This is strictly worse than using an actual iterator. You can iterate over vectors
66directly, so write this:
1a4d82fc 67
85aaf69f
SL
68```rust
69let nums = vec![1, 2, 3];
1a4d82fc 70
c34b1796 71for num in &nums {
1a4d82fc
JJ
72 println!("{}", num);
73}
74```
75
76There are two reasons for this. First, this more directly expresses what we
77mean. We iterate through the entire vector, rather than iterating through
78indexes, and then indexing the vector. Second, this version is more efficient:
79the first version will have extra bounds checking because it used indexing,
80`nums[i]`. But since we yield a reference to each element of the vector in turn
81with the iterator, there's no bounds checking in the second example. This is
82very common with iterators: we can ignore unnecessary bounds checks, but still
83know that we're safe.
84
85There's another detail here that's not 100% clear because of how `println!`
85aaf69f
SL
86works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
87not an `i32` itself. `println!` handles the dereferencing for us, so we don't
1a4d82fc
JJ
88see it. This code works fine too:
89
85aaf69f
SL
90```rust
91let nums = vec![1, 2, 3];
1a4d82fc 92
c34b1796 93for num in &nums {
1a4d82fc
JJ
94 println!("{}", *num);
95}
96```
97
c34b1796
AL
98Now we're explicitly dereferencing `num`. Why does `&nums` give us
99references? Firstly, because we explicitly asked it to with
100`&`. Secondly, if it gave us the data itself, we would have to be its
101owner, which would involve making a copy of the data and giving us the
9cc50fc6
SL
102copy. With references, we're only borrowing a reference to the data,
103and so it's only passing a reference, without needing to do the move.
1a4d82fc 104
85aaf69f 105So, now that we've established that ranges are often not what you want, let's
1a4d82fc
JJ
106talk about what you do want instead.
107
108There are three broad classes of things that are relevant here: iterators,
b039eaaf 109*iterator adaptors*, and *consumers*. Here's some definitions:
1a4d82fc 110
85aaf69f 111* *iterators* give you a sequence of values.
b039eaaf 112* *iterator adaptors* operate on an iterator, producing a new iterator with a
1a4d82fc 113 different output sequence.
85aaf69f 114* *consumers* operate on an iterator, producing some final set of values.
1a4d82fc 115
85aaf69f 116Let's talk about consumers first, since you've already seen an iterator, ranges.
1a4d82fc
JJ
117
118## Consumers
119
85aaf69f 120A *consumer* operates on an iterator, returning some kind of value or values.
1a4d82fc
JJ
121The most common consumer is `collect()`. This code doesn't quite compile,
122but it shows the intention:
123
62682a34 124```rust,ignore
85aaf69f 125let one_to_one_hundred = (1..101).collect();
1a4d82fc
JJ
126```
127
128As you can see, we call `collect()` on our iterator. `collect()` takes
129as many values as the iterator will give it, and returns a collection
130of the results. So why won't this compile? Rust can't determine what
131type of things you want to collect, and so you need to let it know.
132Here's the version that does compile:
133
85aaf69f
SL
134```rust
135let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
1a4d82fc
JJ
136```
137
138If you remember, the `::<>` syntax allows us to give a type hint,
85aaf69f
SL
139and so we tell it that we want a vector of integers. You don't always
140need to use the whole type, though. Using a `_` will let you provide
141a partial hint:
142
143```rust
144let one_to_one_hundred = (1..101).collect::<Vec<_>>();
145```
146
147This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
148`_` is sometimes called a "type placeholder" for this reason.
1a4d82fc
JJ
149
150`collect()` is the most common consumer, but there are others too. `find()`
151is one:
152
85aaf69f
SL
153```rust
154let greater_than_forty_two = (0..100)
1a4d82fc
JJ
155 .find(|x| *x > 42);
156
157match greater_than_forty_two {
b039eaaf
SL
158 Some(_) => println!("Found a match!"),
159 None => println!("No match found :("),
1a4d82fc
JJ
160}
161```
162
163`find` takes a closure, and works on a reference to each element of an
164iterator. This closure returns `true` if the element is the element we're
b039eaaf
SL
165looking for, and `false` otherwise. `find` returns the first element satisfying
166the specified predicate. Because we might not find a matching element, `find`
167returns an `Option` rather than the element itself.
1a4d82fc
JJ
168
169Another important consumer is `fold`. Here's what it looks like:
170
85aaf69f
SL
171```rust
172let sum = (1..4).fold(0, |sum, x| sum + x);
1a4d82fc
JJ
173```
174
175`fold()` is a consumer that looks like this:
176`fold(base, |accumulator, element| ...)`. It takes two arguments: the first
85aaf69f
SL
177is an element called the *base*. The second is a closure that itself takes two
178arguments: the first is called the *accumulator*, and the second is an
179*element*. Upon each iteration, the closure is called, and the result is the
1a4d82fc
JJ
180value of the accumulator on the next iteration. On the first iteration, the
181base is the value of the accumulator.
182
183Okay, that's a bit confusing. Let's examine the values of all of these things
184in this iterator:
185
186| base | accumulator | element | closure result |
187|------|-------------|---------|----------------|
85aaf69f
SL
188| 0 | 0 | 1 | 1 |
189| 0 | 1 | 2 | 3 |
190| 0 | 3 | 3 | 6 |
1a4d82fc
JJ
191
192We called `fold()` with these arguments:
193
85aaf69f
SL
194```rust
195# (1..4)
196.fold(0, |sum, x| sum + x);
1a4d82fc
JJ
197```
198
85aaf69f
SL
199So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the
200first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
201`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
1a4d82fc 202iteration, that value becomes our accumulator, `sum`, and the element is
85aaf69f 203the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
1a4d82fc 204the value of the accumulator for the last iteration. On that iteration,
85aaf69f 205`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
1a4d82fc
JJ
206result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
207
208Whew. `fold` can be a bit strange the first few times you see it, but once it
209clicks, you can use it all over the place. Any time you have a list of things,
210and you want a single result, `fold` is appropriate.
211
212Consumers are important due to one additional property of iterators we haven't
213talked about yet: laziness. Let's talk some more about iterators, and you'll
214see why consumers matter.
215
216## Iterators
217
218As we've said before, an iterator is something that we can call the
219`.next()` method on repeatedly, and it gives us a sequence of things.
220Because you need to call the method, this means that iterators
bd371182 221can be *lazy* and not generate all of the values upfront. This code,
62682a34 222for example, does not actually generate the numbers `1-99`, instead
bd371182 223creating a value that merely represents the sequence:
1a4d82fc 224
85aaf69f
SL
225```rust
226let nums = 1..100;
1a4d82fc
JJ
227```
228
229Since we didn't do anything with the range, it didn't generate the sequence.
230Let's add the consumer:
231
85aaf69f
SL
232```rust
233let nums = (1..100).collect::<Vec<i32>>();
1a4d82fc
JJ
234```
235
85aaf69f 236Now, `collect()` will require that the range gives it some numbers, and so
1a4d82fc
JJ
237it will do the work of generating the sequence.
238
c34b1796
AL
239Ranges are one of two basic iterators that you'll see. The other is `iter()`.
240`iter()` can turn a vector into a simple iterator that gives you each element
241in turn:
1a4d82fc 242
85aaf69f 243```rust
bd371182 244let nums = vec![1, 2, 3];
1a4d82fc
JJ
245
246for num in nums.iter() {
247 println!("{}", num);
248}
249```
250
251These two basic iterators should serve you well. There are some more
bd371182 252advanced iterators, including ones that are infinite.
1a4d82fc 253
b039eaaf 254That's enough about iterators. Iterator adaptors are the last concept
1a4d82fc
JJ
255we need to talk about with regards to iterators. Let's get to it!
256
b039eaaf 257## Iterator adaptors
1a4d82fc 258
b039eaaf 259*Iterator adaptors* take an iterator and modify it somehow, producing
1a4d82fc
JJ
260a new iterator. The simplest one is called `map`:
261
62682a34 262```rust,ignore
85aaf69f 263(1..100).map(|x| x + 1);
1a4d82fc
JJ
264```
265
266`map` is called upon another iterator, and produces a new iterator where each
267element reference has the closure it's been given as an argument called on it.
268So this would give us the numbers from `2-100`. Well, almost! If you
269compile the example, you'll get a warning:
270
85aaf69f 271```text
1a4d82fc
JJ
272warning: unused result which must be used: iterator adaptors are lazy and
273 do nothing unless consumed, #[warn(unused_must_use)] on by default
85aaf69f 274(1..100).map(|x| x + 1);
1a4d82fc
JJ
275 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
276```
277
278Laziness strikes again! That closure will never execute. This example
279doesn't print any numbers:
280
62682a34 281```rust,ignore
85aaf69f 282(1..100).map(|x| println!("{}", x));
1a4d82fc
JJ
283```
284
285If you are trying to execute a closure on an iterator for its side effects,
9cc50fc6 286use `for` instead.
1a4d82fc 287
b039eaaf
SL
288There are tons of interesting iterator adaptors. `take(n)` will return an
289iterator over the next `n` elements of the original iterator. Let's try it out
290with an infinite iterator:
1a4d82fc 291
85aaf69f 292```rust
62682a34 293for i in (1..).take(5) {
1a4d82fc
JJ
294 println!("{}", i);
295}
296```
297
298This will print
299
85aaf69f 300```text
1a4d82fc 3011
62682a34
SL
3022
3033
3044
3055
1a4d82fc
JJ
306```
307
308`filter()` is an adapter that takes a closure as an argument. This closure
309returns `true` or `false`. The new iterator `filter()` produces
b039eaaf 310only the elements that the closure returns `true` for:
1a4d82fc 311
85aaf69f
SL
312```rust
313for i in (1..100).filter(|&x| x % 2 == 0) {
1a4d82fc
JJ
314 println!("{}", i);
315}
316```
317
318This will print all of the even numbers between one and a hundred.
7453a54e
SL
319(Note that, unlike `map`, the closure passed to `filter` is passed a reference
320to the element instead of the element itself. The filter predicate here uses
321the `&x` pattern to extract the integer. The filter closure is passed a
322reference because it returns `true` or `false` instead of the element,
323so the `filter` implementation must retain ownership to put the elements
324into the newly constructed iterator.)
1a4d82fc
JJ
325
326You can chain all three things together: start with an iterator, adapt it
327a few times, and then consume the result. Check it out:
328
85aaf69f 329```rust
62682a34 330(1..)
1a4d82fc
JJ
331 .filter(|&x| x % 2 == 0)
332 .filter(|&x| x % 3 == 0)
333 .take(5)
85aaf69f 334 .collect::<Vec<i32>>();
1a4d82fc
JJ
335```
336
337This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
338
b039eaaf 339This is just a small taste of what iterators, iterator adaptors, and consumers
1a4d82fc
JJ
340can help you with. There are a number of really useful iterators, and you can
341write your own as well. Iterators provide a safe, efficient way to manipulate
342all kinds of lists. They're a little unusual at first, but if you play with
343them, you'll get hooked. For a full list of the different iterators and
344consumers, check out the [iterator module documentation](../std/iter/index.html).