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.
This commit is contained in:
commit
504eaa5929
src/doc/trpl
@ -26,8 +26,7 @@
|
||||
* [Primitive Types](primitive-types.md)
|
||||
* [Comments](comments.md)
|
||||
* [if](if.md)
|
||||
* [for loops](for-loops.md)
|
||||
* [while loops](while-loops.md)
|
||||
* [Loops](loops.md)
|
||||
* [Ownership](ownership.md)
|
||||
* [References and Borrowing](references-and-borrowing.md)
|
||||
* [Lifetimes](lifetimes.md)
|
||||
|
@ -1,85 +0,0 @@
|
||||
% for Loops
|
||||
|
||||
The `for` loop is used to loop a particular number of times. Rust’s `for` loops
|
||||
work a bit differently than in other systems languages, however. Rust’s `for`
|
||||
loop doesn’t look like this “C-style” `for` loop:
|
||||
|
||||
```c
|
||||
for (x = 0; x < 10; x++) {
|
||||
printf( "%d\n", x );
|
||||
}
|
||||
```
|
||||
|
||||
Instead, it looks like this:
|
||||
|
||||
```rust
|
||||
for x in 0..10 {
|
||||
println!("{}", x); // x: i32
|
||||
}
|
||||
```
|
||||
|
||||
In slightly more abstract terms,
|
||||
|
||||
```ignore
|
||||
for var in expression {
|
||||
code
|
||||
}
|
||||
```
|
||||
|
||||
The expression is an [iterator][iterator]. The iterator gives back a series of
|
||||
elements. Each element is one iteration of the loop. That value is then bound
|
||||
to the name `var`, which is valid for the loop body. Once the body is over, the
|
||||
next value is fetched from the iterator, and we loop another time. When there
|
||||
are no more values, the `for` loop is over.
|
||||
|
||||
[iterator]: iterators.html
|
||||
|
||||
In our example, `0..10` is an expression that takes a start and an end position,
|
||||
and gives an iterator over those values. The upper bound is exclusive, though,
|
||||
so our loop will print `0` through `9`, not `10`.
|
||||
|
||||
Rust does not have the “C-style” `for` loop on purpose. Manually controlling
|
||||
each element of the loop is complicated and error prone, even for experienced C
|
||||
developers.
|
||||
|
||||
# Enumerate
|
||||
|
||||
When you need to keep track of how many times you already looped, you can use the `.enumerate()` function.
|
||||
|
||||
## On ranges:
|
||||
|
||||
```rust
|
||||
for (i,j) in (5..10).enumerate() {
|
||||
println!("i = {} and j = {}", i, j);
|
||||
}
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
i = 0 and j = 5
|
||||
i = 1 and j = 6
|
||||
i = 2 and j = 7
|
||||
i = 3 and j = 8
|
||||
i = 4 and j = 9
|
||||
```
|
||||
|
||||
Don't forget to add the parentheses around the range.
|
||||
|
||||
## On iterators:
|
||||
|
||||
```rust
|
||||
# let lines = "hello\nworld".lines();
|
||||
for (linenumber, line) in lines.enumerate() {
|
||||
println!("{}: {}", linenumber, line);
|
||||
}
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
0: Content of line one
|
||||
1: Content of line two
|
||||
2: Content of line tree
|
||||
3: Content of line four
|
||||
```
|
209
src/doc/trpl/loops.md
Normal file
209
src/doc/trpl/loops.md
Normal file
@ -0,0 +1,209 @@
|
||||
% Loops
|
||||
|
||||
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.
|
||||
|
||||
## loop
|
||||
|
||||
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:
|
||||
|
||||
```rust,ignore
|
||||
loop {
|
||||
println!("Loop forever!");
|
||||
}
|
||||
```
|
||||
|
||||
## while
|
||||
|
||||
Rust also has a `while` loop. It looks like this:
|
||||
|
||||
```rust
|
||||
let mut x = 5; // mut x: i32
|
||||
let mut done = false; // mut done: bool
|
||||
|
||||
while !done {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`while` loops are the correct choice when you’re not sure how many times
|
||||
you need to loop.
|
||||
|
||||
If you need an infinite loop, you may be tempted to write this:
|
||||
|
||||
```rust,ignore
|
||||
while true {
|
||||
```
|
||||
|
||||
However, `loop` is far better suited to handle this case:
|
||||
|
||||
```rust,ignore
|
||||
loop {
|
||||
```
|
||||
|
||||
Rust’s control-flow analysis treats this construct differently than a `while
|
||||
true`, since we know that it will always loop. In general, the more information
|
||||
we can give to the compiler, the better it can do with safety and code
|
||||
generation, so you should always prefer `loop` when you plan to loop
|
||||
infinitely.
|
||||
|
||||
## for
|
||||
|
||||
The `for` loop is used to loop a particular number of times. Rust’s `for` loops
|
||||
work a bit differently than in other systems languages, however. Rust’s `for`
|
||||
loop doesn’t look like this “C-style” `for` loop:
|
||||
|
||||
```c
|
||||
for (x = 0; x < 10; x++) {
|
||||
printf( "%d\n", x );
|
||||
}
|
||||
```
|
||||
|
||||
Instead, it looks like this:
|
||||
|
||||
```rust
|
||||
for x in 0..10 {
|
||||
println!("{}", x); // x: i32
|
||||
}
|
||||
```
|
||||
|
||||
In slightly more abstract terms,
|
||||
|
||||
```ignore
|
||||
for var in expression {
|
||||
code
|
||||
}
|
||||
```
|
||||
|
||||
The expression is an [iterator][iterator]. The iterator gives back a series of
|
||||
elements. Each element is one iteration of the loop. That value is then bound
|
||||
to the name `var`, which is valid for the loop body. Once the body is over, the
|
||||
next value is fetched from the iterator, and we loop another time. When there
|
||||
are no more values, the `for` loop is over.
|
||||
|
||||
[iterator]: iterators.html
|
||||
|
||||
In our example, `0..10` is an expression that takes a start and an end position,
|
||||
and gives an iterator over those values. The upper bound is exclusive, though,
|
||||
so our loop will print `0` through `9`, not `10`.
|
||||
|
||||
Rust does not have the “C-style” `for` loop on purpose. Manually controlling
|
||||
each element of the loop is complicated and error prone, even for experienced C
|
||||
developers.
|
||||
|
||||
### Enumerate
|
||||
|
||||
When you need to keep track of how many times you already looped, you can use the `.enumerate()` function.
|
||||
|
||||
#### On ranges:
|
||||
|
||||
```rust
|
||||
for (i,j) in (5..10).enumerate() {
|
||||
println!("i = {} and j = {}", i, j);
|
||||
}
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
i = 0 and j = 5
|
||||
i = 1 and j = 6
|
||||
i = 2 and j = 7
|
||||
i = 3 and j = 8
|
||||
i = 4 and j = 9
|
||||
```
|
||||
|
||||
Don't forget to add the parentheses around the range.
|
||||
|
||||
#### On iterators:
|
||||
|
||||
```rust
|
||||
# let lines = "hello\nworld".lines();
|
||||
for (linenumber, line) in lines.enumerate() {
|
||||
println!("{}: {}", linenumber, line);
|
||||
}
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
0: Content of line one
|
||||
1: Content of line two
|
||||
2: Content of line tree
|
||||
3: Content of line four
|
||||
```
|
||||
|
||||
## Ending iteration early
|
||||
|
||||
Let’s take a look at that `while` loop we had earlier:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
let mut done = false;
|
||||
|
||||
while !done {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
|
||||
when we should exit out of the loop. Rust has two keywords to help us with
|
||||
modifying iteration: `break` and `continue`.
|
||||
|
||||
In this case, we can write the loop in a better way with `break`:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
|
||||
loop {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 { break; }
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
`continue` is similar, but instead of ending the loop, goes to the next
|
||||
iteration. This will only print the odd numbers:
|
||||
|
||||
```rust
|
||||
for x in 0..10 {
|
||||
if x % 2 == 0 { continue; }
|
||||
|
||||
println!("{}", x);
|
||||
}
|
||||
```
|
||||
|
||||
## Loop labels
|
||||
|
||||
You may also encounter situations where you have nested loops and need to
|
||||
specify which one your `break` or `continue` statement is for. Like most
|
||||
other languages, by default a `break` or `continue` will apply to innermost
|
||||
loop. In a sitation where you would like to a `break` or `continue` for one
|
||||
of the outer loops, you can use labels to specify which loop the `break` or
|
||||
`continue` statement applies to. This will only print when both `x` and `y` are
|
||||
odd:
|
||||
|
||||
```rust
|
||||
'outer: for x in 0..10 {
|
||||
'inner: for y in 0..10 {
|
||||
if x % 2 == 0 { continue 'outer; } // continues the loop over x
|
||||
if y % 2 == 0 { continue 'inner; } // continues the loop over y
|
||||
println!("x: {}, y: {}", x, y);
|
||||
}
|
||||
}
|
||||
```
|
@ -1,111 +0,0 @@
|
||||
% while Loops
|
||||
|
||||
Rust also has a `while` loop. It looks like this:
|
||||
|
||||
```rust
|
||||
let mut x = 5; // mut x: i32
|
||||
let mut done = false; // mut done: bool
|
||||
|
||||
while !done {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`while` loops are the correct choice when you’re not sure how many times
|
||||
you need to loop.
|
||||
|
||||
If you need an infinite loop, you may be tempted to write this:
|
||||
|
||||
```rust,ignore
|
||||
while true {
|
||||
```
|
||||
|
||||
However, Rust has a dedicated keyword, `loop`, to handle this case:
|
||||
|
||||
```rust,ignore
|
||||
loop {
|
||||
```
|
||||
|
||||
Rust’s control-flow analysis treats this construct differently than a `while
|
||||
true`, since we know that it will always loop. In general, the more information
|
||||
we can give to the compiler, the better it can do with safety and code
|
||||
generation, so you should always prefer `loop` when you plan to loop
|
||||
infinitely.
|
||||
|
||||
## Ending iteration early
|
||||
|
||||
Let’s take a look at that `while` loop we had earlier:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
let mut done = false;
|
||||
|
||||
while !done {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
|
||||
when we should exit out of the loop. Rust has two keywords to help us with
|
||||
modifying iteration: `break` and `continue`.
|
||||
|
||||
In this case, we can write the loop in a better way with `break`:
|
||||
|
||||
```rust
|
||||
let mut x = 5;
|
||||
|
||||
loop {
|
||||
x += x - 3;
|
||||
|
||||
println!("{}", x);
|
||||
|
||||
if x % 5 == 0 { break; }
|
||||
}
|
||||
```
|
||||
|
||||
We now loop forever with `loop` and use `break` to break out early.
|
||||
|
||||
`continue` is similar, but instead of ending the loop, goes to the next
|
||||
iteration. This will only print the odd numbers:
|
||||
|
||||
```rust
|
||||
for x in 0..10 {
|
||||
if x % 2 == 0 { continue; }
|
||||
|
||||
println!("{}", x);
|
||||
}
|
||||
```
|
||||
|
||||
You may also encounter situations where you have nested loops and need to
|
||||
specify which one your `break` or `continue` statement is for. Like most
|
||||
other languages, by default a `break` or `continue` will apply to innermost
|
||||
loop. In a sitation where you would like to a `break` or `continue` for one
|
||||
of the outer loops, you can use labels to specify which loop the `break` or
|
||||
`continue` statement applies to. This will only print when both `x` and `y` are
|
||||
odd:
|
||||
|
||||
```rust
|
||||
'outer: for x in 0..10 {
|
||||
'inner: for y in 0..10 {
|
||||
if x % 2 == 0 { continue 'outer; } // continues the loop over x
|
||||
if y % 2 == 0 { continue 'inner; } // continues the loop over y
|
||||
println!("x: {}, y: {}", x, y);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
|
||||
|
||||
[for]: for-loops.html
|
Loading…
x
Reference in New Issue
Block a user