Skip to content

Commit 636aff1

Browse files
committed
Guide: looping
1 parent 35e2134 commit 636aff1

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
@@ -958,13 +958,146 @@ Enums
958958

959959
## Looping
960960

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

963-
while
964+
### `for`
964965

965-
loop
966+
The `for` loop is used to loop a particular number of times. Rust's `for` loops
967+
work a bit differently than in other systems languages, however. Rust's `for`
968+
loop doesn't look like this C `for` loop:
966969

967-
break/continue
970+
```{ignore,c}
971+
for (x = 0; x < 10; x++) {
972+
printf( "%d\n", x );
973+
}
974+
```
975+
976+
It looks like this:
977+
978+
```{rust}
979+
for x in range(0i, 10i) {
980+
println!("{:d}", x);
981+
}
982+
```
983+
984+
In slightly more abstract terms,
985+
986+
```{ignore,notrust}
987+
for var in expression {
988+
code
989+
}
990+
```
991+
992+
The expression is an iterator, which we will discuss in more depth later in the
993+
guide. The iterator gives back a series of elements. Each element is one
994+
iteration of the loop. That value is then bound to the name `var`, which is
995+
valid for the loop body. Once the body is over, the next value is fetched from
996+
the iterator, and we loop another time. When there are no more values, the
997+
`for` loop is over.
998+
999+
In our example, the `range` function is a function, provided by Rust, that
1000+
takes a start and an end position, and gives an iterator over those values. The
1001+
upper bound is exclusive, though, so our loop will print `0` through `9`, not
1002+
`10`.
1003+
1004+
Rust does not have the "C style" `for` loop on purpose. Manually controlling
1005+
each element of the loop is complicated and error prone, even for experienced C
1006+
developers. There's an old joke that goes, "There are two hard problems in
1007+
computer science: naming things, cache invalidation, and off-by-one errors."
1008+
The joke, of course, being that the setup says "two hard problems" but then
1009+
lists three things. This happens quite a bit with "C style" `for` loops.
1010+
1011+
We'll talk more about `for` when we cover **vector**s, later in the Guide.
1012+
1013+
### `while`
1014+
1015+
The other kind of looping construct in Rust is the `while` loop. It looks like
1016+
this:
1017+
1018+
```{rust}
1019+
let mut x = 5u;
1020+
let mut done = false;
1021+
1022+
while !done {
1023+
x += x - 3;
1024+
println!("{}", x);
1025+
if x % 5 == 0 { done = true; }
1026+
}
1027+
```
1028+
1029+
`while` loops are the correct choice when you're not sure how many times
1030+
you need to loop.
1031+
1032+
If you need an infinite loop, you may be tempted to write this:
1033+
1034+
```{rust,ignore}
1035+
while true {
1036+
```
1037+
1038+
Rust has a dedicated keyword, `loop`, to handle this case:
1039+
1040+
```{rust,ignore}
1041+
loop {
1042+
```
1043+
1044+
Rust's control-flow analysis treats this construct differently than a
1045+
`while true`, since we know that it will always loop. The details of what
1046+
that _means_ aren't super important to understand at this stage, but in
1047+
general, the more information we can give to the compiler, the better it
1048+
can do with safety and code generation. So you should always prefer
1049+
`loop` when you plan to loop infinitely.
1050+
1051+
### Ending iteration early
1052+
1053+
Let's take a look at that `while` loop we had earlier:
1054+
1055+
```{rust}
1056+
let mut x = 5u;
1057+
let mut done = false;
1058+
1059+
while !done {
1060+
x += x - 3;
1061+
println!("{}", x);
1062+
if x % 5 == 0 { done = true; }
1063+
}
1064+
```
1065+
1066+
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
1067+
when we should skip out of the loop. Rust has two keywords to help us with
1068+
modifying iteration: `break` and `continue`.
1069+
1070+
In this case, we can write the loop in a better way with `break`:
1071+
1072+
```{rust}
1073+
let mut x = 5u;
1074+
1075+
loop {
1076+
x += x - 3;
1077+
println!("{}", x);
1078+
if x % 5 == 0 { break; }
1079+
}
1080+
```
1081+
1082+
We now loop forever with `loop`, and use `break` to break out early.
1083+
1084+
`continue` is similar, but instead of ending the loop, goes to the next
1085+
iteration: This will only print the odd numbers:
1086+
1087+
```
1088+
for x in range(0i, 10i) {
1089+
if x % 2 == 0 { continue; }
1090+
1091+
println!("{:d}", x);
1092+
}
1093+
```
1094+
1095+
Both `continue` and `break` are valid in both kinds of loops.
1096+
1097+
We have now learned all of the most basic Rust concepts. We're ready to start
1098+
building our guessing game, but we need to know how to do one last thing first:
1099+
get input from the keyboard. You can't have a guessing game without the ability
1100+
to guess!
9681101

9691102
## Guessing Game: complete
9701103

0 commit comments

Comments
 (0)