Loops

Rust currently provides three approaches to performing some kind of iterative activity. They are: loop`loop,`, while`whileand` and for`for`. Each approach has its own set of uses.

loop

The infinite loop`loopis the simplest form of loop available in Rust. Using the keywordloop, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infiniteloop`s look like this:

fn main() { loop { println!("Loop forever!"); } }
loop {
    println!("Loop forever!");
}

while

Rust also has a while`while` loop. It looks like this:

fn main() { 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; } } }
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`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:

fn main() { while true { }
while true {

However, loop`loop` is far better suited to handle this case:

fn main() { loop { }
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`loop` when you plan to loop infinitely.

for

The for`forloop is used to loop a particular number of times. Rust’sforloops work a bit differently than in other systems languages, however. Rust’sforloop doesn’t look like this “C-style”for` loop:

for (x = 0; x < 10; x++) {
    printf( "%d\n", x );
}

Instead, it looks like this:

fn main() { for x in 0..10 { println!("{}", x); // x: i32 } }
for x in 0..10 {
    println!("{}", x); // x: i32
}

In slightly more abstract terms,

fn main() { for var in expression { code } }
for var in expression {
    code
}

The expression is an 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`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, thefor` loop is over.

In our example, 0..10`0..10is 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 print0through` through 9`9, not`, not 10`10`.

Rust does not have the “C-style” for`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:

fn main() { for (i,j) in (5..10).enumerate() { println!("i = {} and j = {}", i, j); } }
for (i,j) in (5..10).enumerate() {
    println!("i = {} and j = {}", i, j);
}

Outputs:

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:

fn main() { let lines = "hello\nworld".lines(); for (linenumber, line) in lines.enumerate() { println!("{}: {}", linenumber, line); } }
for (linenumber, line) in lines.enumerate() {
    println!("{}: {}", linenumber, line);
}

Outputs:

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`while` loop we had earlier:

fn main() { let mut x = 5; let mut done = false; while !done { x += x - 3; println!("{}", x); if x % 5 == 0 { done = true; } } }
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`done, to know when we should exit out of the loop. Rust has two keywords to help us with modifying iteration:breakand` and continue`continue`.

In this case, we can write the loop in a better way with break`break`:

fn main() { let mut x = 5; loop { x += x - 3; println!("{}", x); if x % 5 == 0 { break; } } }
let mut x = 5;

loop {
    x += x - 3;

    println!("{}", x);

    if x % 5 == 0 { break; }
}

We now loop forever with loop`loopand use` and use break`breakto break out early. Issuing an explicitreturn` statement will also serve to terminate the loop early.

continue`continue` is similar, but instead of ending the loop, goes to the next iteration. This will only print the odd numbers:

fn main() { for x in 0..10 { if x % 2 == 0 { continue; } println!("{}", x); } }
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`breakor` or continue`continuestatement is for. Like most other languages, by default abreakor` or continue`continuewill apply to innermost loop. In a sitation where you would like to abreakor` or continue`continuefor one of the outer loops, you can use labels to specify which loop thebreakor` or continue`continuestatement applies to. This will only print when bothxand` and y`y` are odd:

fn main() { '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); } } }
'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);
    }
}