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