@@ -4,19 +4,19 @@ Let's talk about loops.
4
4
5
5
Remember Rust's ` for ` loop? Here's an example:
6
6
7
- ``` { rust}
7
+ ``` rust
8
8
for x in 0 .. 10 {
9
9
println! (" {}" , x );
10
10
}
11
11
```
12
12
13
- Now that you know more Rust, we can talk in detail about how this works. The
14
- ` range ` function returns an * iterator * . An iterator is something that we can
13
+ Now that you know more Rust, we can talk in detail about how this works.
14
+ Ranges (the ` 0..10 ` ) are 'iterators' . An iterator is something that we can
15
15
call the ` .next() ` method on repeatedly, and it gives us a sequence of things.
16
16
17
17
Like this:
18
18
19
- ``` { rust}
19
+ ``` rust
20
20
let mut range = 0 .. 10 ;
21
21
22
22
loop {
@@ -29,12 +29,12 @@ loop {
29
29
}
30
30
```
31
31
32
- We make a mutable binding to the return value of ` range ` , which is our iterator.
33
- We then ` loop ` , with an inner ` match ` . This ` match ` is used on the result of
34
- ` range.next() ` , which gives us a reference to the next value of the iterator.
35
- ` next ` returns an ` Option<i32> ` , in this case, which will be ` Some(i32) ` when
36
- we have a value and ` None ` once we run out. If we get ` Some(i32) ` , we print it
37
- out, and if we get ` None ` , we ` break ` out of the loop.
32
+ We make a mutable binding to the range, which is our iterator. We then ` loop ` ,
33
+ with an inner ` match ` . This ` match ` is used on the result of ` range.next() ` ,
34
+ which gives us a reference to the next value of the iterator. ` next ` returns an
35
+ ` Option<i32> ` , in this case, which will be ` Some(i32) ` when we have a value and
36
+ ` None ` once we run out. If we get ` Some(i32) ` , we print it out, and if we get
37
+ ` None ` , we ` break ` out of the loop.
38
38
39
39
This code sample is basically the same as our ` for ` loop version. The ` for `
40
40
loop is just a handy way to write this ` loop ` /` match ` /` break ` construct.
@@ -43,13 +43,13 @@ loop is just a handy way to write this `loop`/`match`/`break` construct.
43
43
own iterator involves implementing the ` Iterator ` trait. While doing that is
44
44
outside of the scope of this guide, Rust provides a number of useful iterators
45
45
to accomplish various tasks. Before we talk about those, we should talk about a
46
- Rust anti-pattern. And that's ` range ` .
46
+ Rust anti-pattern. And that's using ranges like this .
47
47
48
- Yes, we just talked about how ` range ` is cool. But ` range ` is also very
49
- primitive. For example, if you needed to iterate over the contents of
50
- a vector, you may be tempted to write this:
48
+ Yes, we just talked about how ranges are cool. But ranges are also very
49
+ primitive. For example, if you needed to iterate over the contents of a vector,
50
+ you may be tempted to write this:
51
51
52
- ``` { rust}
52
+ ``` rust
53
53
let nums = vec! [1 , 2 , 3 ];
54
54
55
55
for i in 0 .. nums . len () {
@@ -61,7 +61,7 @@ This is strictly worse than using an actual iterator. The `.iter()` method on
61
61
vectors returns an iterator which iterates through a reference to each element
62
62
of the vector in turn. So write this:
63
63
64
- ``` { rust}
64
+ ``` rust
65
65
let nums = vec! [1 , 2 , 3 ];
66
66
67
67
for num in nums . iter () {
@@ -83,7 +83,7 @@ works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
83
83
not an ` i32 ` itself. ` println! ` handles the dereferencing for us, so we don't
84
84
see it. This code works fine too:
85
85
86
- ``` { rust}
86
+ ``` rust
87
87
let nums = vec! [1 , 2 , 3 ];
88
88
89
89
for num in nums . iter () {
@@ -97,7 +97,7 @@ involve making a copy of the data and giving us the copy. With references,
97
97
we're just borrowing a reference to the data, and so it's just passing
98
98
a reference, without needing to do the copy.
99
99
100
- So, now that we've established that ` range ` is often not what you want, let's
100
+ So, now that we've established that ranges are often not what you want, let's
101
101
talk about what you do want instead.
102
102
103
103
There are three broad classes of things that are relevant here: iterators,
@@ -108,8 +108,7 @@ There are three broad classes of things that are relevant here: iterators,
108
108
different output sequence.
109
109
* * consumers* operate on an iterator, producing some final set of values.
110
110
111
- Let's talk about consumers first, since you've already seen an iterator,
112
- ` range ` .
111
+ Let's talk about consumers first, since you've already seen an iterator, ranges.
113
112
114
113
## Consumers
115
114
@@ -118,7 +117,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
118
117
but it shows the intention:
119
118
120
119
``` {rust,ignore}
121
- let one_to_one_hundred = (1..101i32 ).collect();
120
+ let one_to_one_hundred = (1..101 ).collect();
122
121
```
123
122
124
123
As you can see, we call ` collect() ` on our iterator. ` collect() ` takes
@@ -127,8 +126,8 @@ of the results. So why won't this compile? Rust can't determine what
127
126
type of things you want to collect, and so you need to let it know.
128
127
Here's the version that does compile:
129
128
130
- ``` { rust}
131
- let one_to_one_hundred = (1..101i32 ).collect::<Vec<i32>>();
129
+ ``` rust
130
+ let one_to_one_hundred = (1 .. 101 ). collect :: <Vec <i32 >>();
132
131
```
133
132
134
133
If you remember, the ` ::<> ` syntax allows us to give a type hint,
@@ -137,7 +136,7 @@ need to use the whole type, though. Using a `_` will let you provide
137
136
a partial hint:
138
137
139
138
``` rust
140
- let one_to_one_hundred = range ( 1 , 101 ). collect :: <Vec <_ >>();
139
+ let one_to_one_hundred = ( 1 .. 101 ). collect :: <Vec <_ >>();
141
140
```
142
141
143
142
This says "Collect into a ` Vec<T> ` , please, but infer what the ` T ` is for me."
@@ -146,8 +145,8 @@ This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
146
145
` collect() ` is the most common consumer, but there are others too. ` find() `
147
146
is one:
148
147
149
- ``` { rust}
150
- let greater_than_forty_two = (0..100i32 )
148
+ ``` rust
149
+ let greater_than_forty_two = (0 .. 100 )
151
150
. find (| x | * x > 42 );
152
151
153
152
match greater_than_forty_two {
@@ -163,9 +162,8 @@ element, `find` returns an `Option` rather than the element itself.
163
162
164
163
Another important consumer is ` fold ` . Here's what it looks like:
165
164
166
- ``` {rust}
167
- let sum = (1..4)
168
- .fold(0, |sum, x| sum + x);
165
+ ``` rust
166
+ let sum = (1 .. 4 ). fold (0 , | sum , x | sum + x );
169
167
```
170
168
171
169
` fold() ` is a consumer that looks like this:
@@ -187,7 +185,7 @@ in this iterator:
187
185
188
186
We called ` fold() ` with these arguments:
189
187
190
- ``` { rust}
188
+ ``` rust
191
189
# (1 .. 4 )
192
190
. fold (0 , | sum , x | sum + x );
193
191
```
@@ -218,25 +216,25 @@ are *lazy* and don't need to generate all of the values upfront.
218
216
This code, for example, does not actually generate the numbers
219
217
` 1-100 ` , and just creates a value that represents the sequence:
220
218
221
- ``` { rust}
219
+ ``` rust
222
220
let nums = 1 .. 100 ;
223
221
```
224
222
225
223
Since we didn't do anything with the range, it didn't generate the sequence.
226
224
Let's add the consumer:
227
225
228
- ``` { rust}
226
+ ``` rust
229
227
let nums = (1 .. 100 ). collect :: <Vec <i32 >>();
230
228
```
231
229
232
230
Now, ` collect() ` will require that the range gives it some numbers, and so
233
231
it will do the work of generating the sequence.
234
232
235
- A range is one of two basic iterators that you'll see. The other is ` iter() ` ,
233
+ Ranges are one of two basic iterators that you'll see. The other is ` iter() ` ,
236
234
which you've used before. ` iter() ` can turn a vector into a simple iterator
237
235
that gives you each element in turn:
238
236
239
- ``` { rust}
237
+ ``` rust
240
238
let nums = [1 , 2 , 3 ];
241
239
242
240
for num in nums . iter () {
@@ -247,7 +245,7 @@ for num in nums.iter() {
247
245
These two basic iterators should serve you well. There are some more
248
246
advanced iterators, including ones that are infinite. Like ` count ` :
249
247
250
- ``` { rust}
248
+ ``` rust
251
249
std :: iter :: count (1 , 5 );
252
250
```
253
251
@@ -265,15 +263,15 @@ we need to talk about with regards to iterators. Let's get to it!
265
263
a new iterator. The simplest one is called ` map ` :
266
264
267
265
``` {rust,ignore}
268
- (1..100i32 ).map(|x| x + 1);
266
+ (1..100 ).map(|x| x + 1);
269
267
```
270
268
271
269
` map ` is called upon another iterator, and produces a new iterator where each
272
270
element reference has the closure it's been given as an argument called on it.
273
271
So this would give us the numbers from ` 2-100 ` . Well, almost! If you
274
272
compile the example, you'll get a warning:
275
273
276
- ``` {notrust,ignore}
274
+ ``` text
277
275
warning: unused result which must be used: iterator adaptors are lazy and
278
276
do nothing unless consumed, #[warn(unused_must_use)] on by default
279
277
(1..100).map(|x| x + 1);
@@ -295,15 +293,15 @@ iterator over the next `n` elements of the original iterator, note that this
295
293
has no side effect on the original iterator. Let's try it out with our infinite
296
294
iterator from before, ` count() ` :
297
295
298
- ``` { rust}
296
+ ``` rust
299
297
for i in std :: iter :: count (1 , 5 ). take (5 ) {
300
298
println! (" {}" , i );
301
299
}
302
300
```
303
301
304
302
This will print
305
303
306
- ``` {notrust,ignore}
304
+ ``` text
307
305
1
308
306
6
309
307
11
@@ -315,8 +313,8 @@ This will print
315
313
returns ` true ` or ` false ` . The new iterator ` filter() ` produces
316
314
only the elements that that closure returns ` true ` for:
317
315
318
- ``` { rust}
319
- for i in (1..100i32 ).filter(|&x| x % 2 == 0) {
316
+ ``` rust
317
+ for i in (1 .. 100 ). filter (| & x | x % 2 == 0 ) {
320
318
println! (" {}" , i );
321
319
}
322
320
```
@@ -330,8 +328,8 @@ itself.)
330
328
You can chain all three things together: start with an iterator, adapt it
331
329
a few times, and then consume the result. Check it out:
332
330
333
- ``` { rust}
334
- (1..1000i32 )
331
+ ``` rust
332
+ (1 .. 1000 )
335
333
. filter (| & x | x % 2 == 0 )
336
334
. filter (| & x | x % 3 == 0 )
337
335
. take (5 )
0 commit comments