diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 85f0019276e..24686e772e3 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -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) diff --git a/src/doc/trpl/for-loops.md b/src/doc/trpl/for-loops.md deleted file mode 100644 index 2866cee3a1a..00000000000 --- a/src/doc/trpl/for-loops.md +++ /dev/null @@ -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 -``` diff --git a/src/doc/trpl/loops.md b/src/doc/trpl/loops.md new file mode 100644 index 00000000000..a91fb8dadaf --- /dev/null +++ b/src/doc/trpl/loops.md @@ -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); + } +} +``` diff --git a/src/doc/trpl/while-loops.md b/src/doc/trpl/while-loops.md deleted file mode 100644 index 124ebc7d69d..00000000000 --- a/src/doc/trpl/while-loops.md +++ /dev/null @@ -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