1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
% Loops
Rust currently provides three approaches to performing some kind of iterative activity. They are: `loop`, `while` and `for`. Each approach has its own set of uses.
## loop
The infinite `loop` is the simplest form of loop available in Rust. Using the keyword `loop`, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infinite `loop`s look like this:
```rust,ignore
loop {
println!("Loop forever!");
}
```
## while
Rust also has a `while` loop. It looks like this:
```rust
let mut x = 5; // mut x: i32
let mut done = false; // mut done: bool
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
`while` loops are the correct choice when you’re not sure how many times
you need to loop.
If you need an infinite loop, you may be tempted to write this:
```rust,ignore
while true {
```
However, `loop` is far better suited to handle this case:
```rust,ignore
loop {
```
Rust’s control-flow analysis treats this construct differently than a `while
true`, since we know that it will always loop. In general, the more information
we can give to the compiler, the better it can do with safety and code
generation, so you should always prefer `loop` when you plan to loop
infinitely.
## for
The `for` loop is used to loop a particular number of times. Rust’s `for` loops
work a bit differently than in other systems languages, however. Rust’s `for`
loop doesn’t look like this “C-style” `for` loop:
```c
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
```
Instead, it looks like this:
```rust
for x in 0..10 {
println!("{}", x); // x: i32
}
```
In slightly more abstract terms,
```ignore
for var in expression {
code
}
```
The expression is an [iterator][iterator]. The iterator gives back a series of
elements. Each element is one iteration of the loop. That value is then bound
to the name `var`, which is valid for the loop body. Once the body is over, the
next value is fetched from the iterator, and we loop another time. When there
are no more values, the `for` loop is over.
[iterator]: iterators.html
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the “C-style” `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
### Enumerate
When you need to keep track of how many times you already looped, you can use the `.enumerate()` function.
#### On ranges:
```rust
for (i,j) in (5..10).enumerate() {
println!("i = {} and j = {}", i, j);
}
```
Outputs:
```text
i = 0 and j = 5
i = 1 and j = 6
i = 2 and j = 7
i = 3 and j = 8
i = 4 and j = 9
```
Don't forget to add the parentheses around the range.
#### On iterators:
```rust
# let lines = "hello\nworld".lines();
for (linenumber, line) in lines.enumerate() {
println!("{}: {}", linenumber, line);
}
```
Outputs:
```text
0: Content of line one
1: Content of line two
2: Content of line tree
3: Content of line four
```
## Ending iteration early
Let’s take a look at that `while` loop we had earlier:
```rust
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should exit out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```rust
let mut x = 5;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```
We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early.
`continue` is similar, but instead of ending the loop, goes to the next
iteration. This will only print the odd numbers:
```rust
for x in 0..10 {
if x % 2 == 0 { continue; }
println!("{}", x);
}
```
## Loop labels
You may also encounter situations where you have nested loops and need to
specify which one your `break` or `continue` statement is for. Like most
other languages, by default a `break` or `continue` will apply to innermost
loop. In a sitation where you would like to a `break` or `continue` for one
of the outer loops, you can use labels to specify which loop the `break` or
`continue` statement applies to. This will only print when both `x` and `y` are
odd:
```rust
'outer: for x in 0..10 {
'inner: for y in 0..10 {
if x % 2 == 0 { continue 'outer; } // continues the loop over x
if y % 2 == 0 { continue 'inner; } // continues the loop over y
println!("x: {}, y: {}", x, y);
}
}
```
|