]> git.proxmox.com Git - rustc.git/blob - src/doc/trpl/loops.md
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / doc / trpl / 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 ```ignore
78 for var in expression {
79 code
80 }
81 ```
82
83 The expression is an [iterator][iterator]. The iterator gives back a series of
84 elements. Each element is one iteration of the loop. That value is then bound
85 to the name `var`, which is valid for the loop body. Once the body is over, the
86 next value is fetched from the iterator, and we loop another time. When there
87 are no more values, the `for` loop is over.
88
89 [iterator]: iterators.html
90
91 In our example, `0..10` is an expression that takes a start and an end position,
92 and gives an iterator over those values. The upper bound is exclusive, though,
93 so our loop will print `0` through `9`, not `10`.
94
95 Rust does not have the “C-style” `for` loop on purpose. Manually controlling
96 each element of the loop is complicated and error prone, even for experienced C
97 developers.
98
99 ### Enumerate
100
101 When you need to keep track of how many times you already looped, you can use the `.enumerate()` function.
102
103 #### On ranges:
104
105 ```rust
106 for (i,j) in (5..10).enumerate() {
107 println!("i = {} and j = {}", i, j);
108 }
109 ```
110
111 Outputs:
112
113 ```text
114 i = 0 and j = 5
115 i = 1 and j = 6
116 i = 2 and j = 7
117 i = 3 and j = 8
118 i = 4 and j = 9
119 ```
120
121 Don't forget to add the parentheses around the range.
122
123 #### On iterators:
124
125 ```rust
126 # let lines = "hello\nworld".lines();
127 for (linenumber, line) in lines.enumerate() {
128 println!("{}: {}", linenumber, line);
129 }
130 ```
131
132 Outputs:
133
134 ```text
135 0: Content of line one
136 1: Content of line two
137 2: Content of line tree
138 3: Content of line four
139 ```
140
141 ## Ending iteration early
142
143 Let’s take a look at that `while` loop we had earlier:
144
145 ```rust
146 let mut x = 5;
147 let mut done = false;
148
149 while !done {
150 x += x - 3;
151
152 println!("{}", x);
153
154 if x % 5 == 0 {
155 done = true;
156 }
157 }
158 ```
159
160 We had to keep a dedicated `mut` boolean variable binding, `done`, to know
161 when we should exit out of the loop. Rust has two keywords to help us with
162 modifying iteration: `break` and `continue`.
163
164 In this case, we can write the loop in a better way with `break`:
165
166 ```rust
167 let mut x = 5;
168
169 loop {
170 x += x - 3;
171
172 println!("{}", x);
173
174 if x % 5 == 0 { break; }
175 }
176 ```
177
178 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.
179
180 `continue` is similar, but instead of ending the loop, goes to the next
181 iteration. This will only print the odd numbers:
182
183 ```rust
184 for x in 0..10 {
185 if x % 2 == 0 { continue; }
186
187 println!("{}", x);
188 }
189 ```
190
191 ## Loop labels
192
193 You may also encounter situations where you have nested loops and need to
194 specify which one your `break` or `continue` statement is for. Like most
195 other languages, by default a `break` or `continue` will apply to innermost
196 loop. In a sitation where you would like to a `break` or `continue` for one
197 of the outer loops, you can use labels to specify which loop the `break` or
198 `continue` statement applies to. This will only print when both `x` and `y` are
199 odd:
200
201 ```rust
202 'outer: for x in 0..10 {
203 'inner: for y in 0..10 {
204 if x % 2 == 0 { continue 'outer; } // continues the loop over x
205 if y % 2 == 0 { continue 'inner; } // continues the loop over y
206 println!("x: {}, y: {}", x, y);
207 }
208 }
209 ```