Rust Essentials(Second Edition)
上QQ阅读APP看书,第一时间看更新

Looping

For repeating pieces of code, Rust has the common while loop, again without parentheses around the condition:

// from Chapter 3/code/loops.rs 
fn main() { 
  let max_power = 10; 
  let mut power = 1; 
    while power < max_power { 
        print!("{} ", power); // prints without newline 
        power += 1;           // increment counter 
    } 
} 

This prints the following output:

    1 2 3 4 5 6 7 8 9

To start an infinite loop, use the loop statement, as shown below:

loop { 
        power += 1; 
        if power == 42 { 
            // Skip the rest of this iteration 
        continue; 
        } 
        print!("{}  ", power); 
        if power == 50 { 
           print!("OK, that's enough for today"); 
        break;  // exit the loop 
        } 
} 

All the power values including 50 but except 42 are printed; then the loop stops with the statement break. The value 42 is not printed because of the continue statement. So, loop is equivalent to a while true and a loop with a conditioned break simulates a do while in other languages.

When loops are nested inside each other, the break and continue statements apply to the immediate enclosing loop. Any loop statement (also the while and for loop which we'll see next) can be preceded by a label (denoted as labelname:) to allow us to jump to the next or outer enclosing loop, as in this snippet:

  'outer: loop { 
        println!("Entered the outer dungeon."); 
        inner: loop { 
            println!("Entered the inner dungeon."); 
            // break;    // this would break out of the inner loop 
            break 'outer; // breaks to the outer loop 
        } 
        println!("This treasure can sadly never be reached."); 
    } 
    println!("Exited the outer dungeon!"); 

This prints the following output:

    Entered the outer dungeon.
    Entered the inner dungeon.
    Exited the outer dungeon!

Obviously, the use of labels makes reading the code more difficult, so use it wisely. The infamous goto statement from C luckily does not exist in Rust!

Looping where a variable var begins from a start value a to an end value b (exclusive) is done with a for loop over a range expression, as shown in the following statement:

for var in a..b 

Here is an example which prints the squares of the numbers 1 to 10:

for n in 1..11 { 
      println!("The square of {} is {}", n, n * n); 
} 

In general, for in loops over an iterator, which is an object that gives back a series of values one by one. The range a..b is the simplest form of iterator.

Each subsequent value is bound to the variable n and used in the next loop iteration. The for loop ends when there are no more values and the variable n then goes out of scope. If we don't need the value of the variable n in the loop, we can replace it with an _ (underscore), like this:

for _ in 1..11 { } 

The many bugs in C-style for loops, like the off-by-one error with the counter, cannot occur here, because we loop over an iterator.

Variables can also be used in a range, like in the following snippet which prints nine dots:

let mut x = 10; 
for _ in 1..x { x -= 1; print!("."); } 

We'll examine iterators in more detail in Chapter 5, Higher Order Functions and Error-Handling.