Skip to content

Commit 5cef16e

Browse files
committed
auto merge of #15531 : steveklabnik/rust/guide_looping, r=brson
2 parents 2eadfe4 + 636aff1 commit 5cef16e

File tree

1 file changed

+137
-4
lines changed

1 file changed

+137
-4
lines changed

src/doc/guide.md

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,13 +1362,146 @@ string where we don't need to, but sometimes, it's a nice pattern.
13621362

13631363
## Looping
13641364

1365-
for
1365+
Looping is the last basic construct that we haven't learned yet in Rust. Rust has
1366+
two main looping constructs: `for` and `while`.
13661367

1367-
while
1368+
### `for`
13681369

1369-
loop
1370+
The `for` loop is used to loop a particular number of times. Rust's `for` loops
1371+
work a bit differently than in other systems languages, however. Rust's `for`
1372+
loop doesn't look like this C `for` loop:
13701373

1371-
break/continue
1374+
```{ignore,c}
1375+
for (x = 0; x < 10; x++) {
1376+
printf( "%d\n", x );
1377+
}
1378+
```
1379+
1380+
It looks like this:
1381+
1382+
```{rust}
1383+
for x in range(0i, 10i) {
1384+
println!("{:d}", x);
1385+
}
1386+
```
1387+
1388+
In slightly more abstract terms,
1389+
1390+
```{ignore,notrust}
1391+
for var in expression {
1392+
code
1393+
}
1394+
```
1395+
1396+
The expression is an iterator, which we will discuss in more depth later in the
1397+
guide. The iterator gives back a series of elements. Each element is one
1398+
iteration of the loop. That value is then bound to the name `var`, which is
1399+
valid for the loop body. Once the body is over, the next value is fetched from
1400+
the iterator, and we loop another time. When there are no more values, the
1401+
`for` loop is over.
1402+
1403+
In our example, the `range` function is a function, provided by Rust, that
1404+
takes a start and an end position, and gives an iterator over those values. The
1405+
upper bound is exclusive, though, so our loop will print `0` through `9`, not
1406+
`10`.
1407+
1408+
Rust does not have the "C style" `for` loop on purpose. Manually controlling
1409+
each element of the loop is complicated and error prone, even for experienced C
1410+
developers. There's an old joke that goes, "There are two hard problems in
1411+
computer science: naming things, cache invalidation, and off-by-one errors."
1412+
The joke, of course, being that the setup says "two hard problems" but then
1413+
lists three things. This happens quite a bit with "C style" `for` loops.
1414+
1415+
We'll talk more about `for` when we cover **vector**s, later in the Guide.
1416+
1417+
### `while`
1418+
1419+
The other kind of looping construct in Rust is the `while` loop. It looks like
1420+
this:
1421+
1422+
```{rust}
1423+
let mut x = 5u;
1424+
let mut done = false;
1425+
1426+
while !done {
1427+
x += x - 3;
1428+
println!("{}", x);
1429+
if x % 5 == 0 { done = true; }
1430+
}
1431+
```
1432+
1433+
`while` loops are the correct choice when you're not sure how many times
1434+
you need to loop.
1435+
1436+
If you need an infinite loop, you may be tempted to write this:
1437+
1438+
```{rust,ignore}
1439+
while true {
1440+
```
1441+
1442+
Rust has a dedicated keyword, `loop`, to handle this case:
1443+
1444+
```{rust,ignore}
1445+
loop {
1446+
```
1447+
1448+
Rust's control-flow analysis treats this construct differently than a
1449+
`while true`, since we know that it will always loop. The details of what
1450+
that _means_ aren't super important to understand at this stage, but in
1451+
general, the more information we can give to the compiler, the better it
1452+
can do with safety and code generation. So you should always prefer
1453+
`loop` when you plan to loop infinitely.
1454+
1455+
### Ending iteration early
1456+
1457+
Let's take a look at that `while` loop we had earlier:
1458+
1459+
```{rust}
1460+
let mut x = 5u;
1461+
let mut done = false;
1462+
1463+
while !done {
1464+
x += x - 3;
1465+
println!("{}", x);
1466+
if x % 5 == 0 { done = true; }
1467+
}
1468+
```
1469+
1470+
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
1471+
when we should skip out of the loop. Rust has two keywords to help us with
1472+
modifying iteration: `break` and `continue`.
1473+
1474+
In this case, we can write the loop in a better way with `break`:
1475+
1476+
```{rust}
1477+
let mut x = 5u;
1478+
1479+
loop {
1480+
x += x - 3;
1481+
println!("{}", x);
1482+
if x % 5 == 0 { break; }
1483+
}
1484+
```
1485+
1486+
We now loop forever with `loop`, and use `break` to break out early.
1487+
1488+
`continue` is similar, but instead of ending the loop, goes to the next
1489+
iteration: This will only print the odd numbers:
1490+
1491+
```
1492+
for x in range(0i, 10i) {
1493+
if x % 2 == 0 { continue; }
1494+
1495+
println!("{:d}", x);
1496+
}
1497+
```
1498+
1499+
Both `continue` and `break` are valid in both kinds of loops.
1500+
1501+
We have now learned all of the most basic Rust concepts. We're ready to start
1502+
building our guessing game, but we need to know how to do one last thing first:
1503+
get input from the keyboard. You can't have a guessing game without the ability
1504+
to guess!
13721505

13731506
## Guessing Game: complete
13741507

0 commit comments

Comments
 (0)