Skip to content

Commit 817f3a4

Browse files
committed
Remove use of range() in iterator docs.
Fixes #21577.
1 parent c5db290 commit 817f3a4

File tree

1 file changed

+41
-43
lines changed

1 file changed

+41
-43
lines changed

src/doc/trpl/iterators.md

+41-43
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@ Let's talk about loops.
44

55
Remember Rust's `for` loop? Here's an example:
66

7-
```{rust}
7+
```rust
88
for x in 0..10 {
99
println!("{}", x);
1010
}
1111
```
1212

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
1515
call the `.next()` method on repeatedly, and it gives us a sequence of things.
1616

1717
Like this:
1818

19-
```{rust}
19+
```rust
2020
let mut range = 0..10;
2121

2222
loop {
@@ -29,12 +29,12 @@ loop {
2929
}
3030
```
3131

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.
3838

3939
This code sample is basically the same as our `for` loop version. The `for`
4040
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.
4343
own iterator involves implementing the `Iterator` trait. While doing that is
4444
outside of the scope of this guide, Rust provides a number of useful iterators
4545
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.
4747

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:
5151

52-
```{rust}
52+
```rust
5353
let nums = vec![1, 2, 3];
5454

5555
for i in 0..nums.len() {
@@ -61,7 +61,7 @@ This is strictly worse than using an actual iterator. The `.iter()` method on
6161
vectors returns an iterator which iterates through a reference to each element
6262
of the vector in turn. So write this:
6363

64-
```{rust}
64+
```rust
6565
let nums = vec![1, 2, 3];
6666

6767
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`,
8383
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
8484
see it. This code works fine too:
8585

86-
```{rust}
86+
```rust
8787
let nums = vec![1, 2, 3];
8888

8989
for num in nums.iter() {
@@ -97,7 +97,7 @@ involve making a copy of the data and giving us the copy. With references,
9797
we're just borrowing a reference to the data, and so it's just passing
9898
a reference, without needing to do the copy.
9999

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
101101
talk about what you do want instead.
102102

103103
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,
108108
different output sequence.
109109
* *consumers* operate on an iterator, producing some final set of values.
110110

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.
113112

114113
## Consumers
115114

@@ -118,7 +117,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
118117
but it shows the intention:
119118

120119
```{rust,ignore}
121-
let one_to_one_hundred = (1..101i32).collect();
120+
let one_to_one_hundred = (1..101).collect();
122121
```
123122

124123
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
127126
type of things you want to collect, and so you need to let it know.
128127
Here's the version that does compile:
129128

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>>();
132131
```
133132

134133
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
137136
a partial hint:
138137

139138
```rust
140-
let one_to_one_hundred = range(1, 101).collect::<Vec<_>>();
139+
let one_to_one_hundred = (1..101).collect::<Vec<_>>();
141140
```
142141

143142
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."
146145
`collect()` is the most common consumer, but there are others too. `find()`
147146
is one:
148147

149-
```{rust}
150-
let greater_than_forty_two = (0..100i32)
148+
```rust
149+
let greater_than_forty_two = (0..100)
151150
.find(|x| *x > 42);
152151

153152
match greater_than_forty_two {
@@ -163,9 +162,8 @@ element, `find` returns an `Option` rather than the element itself.
163162

164163
Another important consumer is `fold`. Here's what it looks like:
165164

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);
169167
```
170168

171169
`fold()` is a consumer that looks like this:
@@ -187,7 +185,7 @@ in this iterator:
187185

188186
We called `fold()` with these arguments:
189187

190-
```{rust}
188+
```rust
191189
# (1..4)
192190
.fold(0, |sum, x| sum + x);
193191
```
@@ -218,25 +216,25 @@ are *lazy* and don't need to generate all of the values upfront.
218216
This code, for example, does not actually generate the numbers
219217
`1-100`, and just creates a value that represents the sequence:
220218

221-
```{rust}
219+
```rust
222220
let nums = 1..100;
223221
```
224222

225223
Since we didn't do anything with the range, it didn't generate the sequence.
226224
Let's add the consumer:
227225

228-
```{rust}
226+
```rust
229227
let nums = (1..100).collect::<Vec<i32>>();
230228
```
231229

232230
Now, `collect()` will require that the range gives it some numbers, and so
233231
it will do the work of generating the sequence.
234232

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()`,
236234
which you've used before. `iter()` can turn a vector into a simple iterator
237235
that gives you each element in turn:
238236

239-
```{rust}
237+
```rust
240238
let nums = [1, 2, 3];
241239

242240
for num in nums.iter() {
@@ -247,7 +245,7 @@ for num in nums.iter() {
247245
These two basic iterators should serve you well. There are some more
248246
advanced iterators, including ones that are infinite. Like `count`:
249247

250-
```{rust}
248+
```rust
251249
std::iter::count(1, 5);
252250
```
253251

@@ -265,15 +263,15 @@ we need to talk about with regards to iterators. Let's get to it!
265263
a new iterator. The simplest one is called `map`:
266264

267265
```{rust,ignore}
268-
(1..100i32).map(|x| x + 1);
266+
(1..100).map(|x| x + 1);
269267
```
270268

271269
`map` is called upon another iterator, and produces a new iterator where each
272270
element reference has the closure it's been given as an argument called on it.
273271
So this would give us the numbers from `2-100`. Well, almost! If you
274272
compile the example, you'll get a warning:
275273

276-
```{notrust,ignore}
274+
```text
277275
warning: unused result which must be used: iterator adaptors are lazy and
278276
do nothing unless consumed, #[warn(unused_must_use)] on by default
279277
(1..100).map(|x| x + 1);
@@ -295,15 +293,15 @@ iterator over the next `n` elements of the original iterator, note that this
295293
has no side effect on the original iterator. Let's try it out with our infinite
296294
iterator from before, `count()`:
297295

298-
```{rust}
296+
```rust
299297
for i in std::iter::count(1, 5).take(5) {
300298
println!("{}", i);
301299
}
302300
```
303301

304302
This will print
305303

306-
```{notrust,ignore}
304+
```text
307305
1
308306
6
309307
11
@@ -315,8 +313,8 @@ This will print
315313
returns `true` or `false`. The new iterator `filter()` produces
316314
only the elements that that closure returns `true` for:
317315

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) {
320318
println!("{}", i);
321319
}
322320
```
@@ -330,8 +328,8 @@ itself.)
330328
You can chain all three things together: start with an iterator, adapt it
331329
a few times, and then consume the result. Check it out:
332330

333-
```{rust}
334-
(1..1000i32)
331+
```rust
332+
(1..1000)
335333
.filter(|&x| x % 2 == 0)
336334
.filter(|&x| x % 3 == 0)
337335
.take(5)

0 commit comments

Comments
 (0)