Skip to content

Commit 504eaa5

Browse files
committed
Auto merge of #27305 - KieranHunt:master, r=steveklabnik
I found that the book had little information for `loop`s and `loop` label so I've added some.
2 parents 30ba0ee + a989ed8 commit 504eaa5

File tree

4 files changed

+210
-198
lines changed

4 files changed

+210
-198
lines changed

src/doc/trpl/SUMMARY.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
* [Primitive Types](primitive-types.md)
2727
* [Comments](comments.md)
2828
* [if](if.md)
29-
* [for loops](for-loops.md)
30-
* [while loops](while-loops.md)
29+
* [Loops](loops.md)
3130
* [Ownership](ownership.md)
3231
* [References and Borrowing](references-and-borrowing.md)
3332
* [Lifetimes](lifetimes.md)

src/doc/trpl/for-loops.md

-85
This file was deleted.

src/doc/trpl/loops.md

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
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+
```

0 commit comments

Comments
 (0)