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