Rust Iteration Control (for & while loops) Tutorial

In this Rust tutorial we learn how for and while loops allow us to conditionally iterate over sections of code multiple times, helping us to control the flow of our Rust application.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is a loop

Throughout our application, we will often need to execute sections of code more than once.

Instead of rewriting these sections of code, we can place them in a loop and allow Rust to automatically execute them as many times as we need.

A loop consists of the following:

  • A condition
  • A code block containing our execution code

The compiler will evaluate the condition and based on its results, execute the code. Then, the compiler will start again at the top of the loop code and evaluate the condition again.

This cycle of iterations continue until the condition is false, or we manually stop the loop.

Rust provides us with two types of loops:

  • The while loop
  • The for loop

The indefinite while loop

The while loop will continue to execute code while its condition remains true. Once the condition proves false, the while loop will stop and the compiler will move on to any code below it.

Syntax: while loop
while condition {

    // code to execute
    // while condition
    // remains true

}
Example: while loop
fn main() {

    let mut counter = 0;

    while counter < 10 {

        println!("Counter: {}", counter);
        counter += 1;
    }
}

It may seem a little confusing so let’s take it step by step.

  1. First, we set up a mutable variable called counter. This will help us stop the loop.
  2. Next, we specify our condition that while the counter variable value is less than 10, the loop should iterate.
  3. Inside the while code block, we print out the counter number to the console.
  4. Lastly, we add 1 to our counter variable to indicate that the loop iterated once.

When we run the example, the output shows a list of numbers from 1 to 10.

Output:
Counter: 0
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
Counter: 6
Counter: 7
Counter: 8
Counter: 9

So what exactly happened?

  1. The compiler saw that counter was less than 10, so it executed the code in the code block.
  2. In the code block we printed the counter number at that stage.
  3. Then, we added 1 to the counter so that it now contains the number 1.
  4. Because the condition proved true, the compiler will go back to the top of the while loop and evaluate it again.
  5. When it got back to the top, the evaluation proved true again. So, the compiler executed the code in the code block again.

This continued on in a loop until the compiler saw that the counter value was 10. This made the evaluation prove false so the compiler stopped the loop.

Infinite loops

With the while loop, there is a potential danger that the loop may never stop if we make a mistake. This is known as an infinite loop and it will significantly slow down the system until the application crashes.

Let’s use our earlier example. If we remove the code that increments the counter, the condition will always prove true because the counter will stay at 0 and never get to 10 where it’s told to stop.

The following example will cause an infinite loop. To stop the application, right-click in the Console tab in Eclipse and choose Terminate/Disconnect all.

Example: infinite loop
fn main() {

    let mut counter = 0;

    while counter < 10 {

        println!("Counter: {}", counter);
    }
}

When we use a while loop, we should be mindful of how and when it will stop.

The definite for loop

The for loop in Rust is definite. That’s to say, we know beforehand how many times it will run. The for loop comes in two variations.

If you’re familiar with other languages like C#, the for loop in Rust is like a combination of the foreach and for loopsOpens up in a new page in C#.

Let’s look at the syntax and an example first, then explain what’s happening.

Syntax: for loop
for temp_variable in lower_bound..upper_bound {

    // use temp_variable

}
Example: for loop
fn main() {

    for x in 0..10 {

        println!("{}", x);
    }

}

When we run the example above, the numbers 0 to 9 are printed to the console.

In this variation of the for loop, the lower_bound and upper_bound essentially makes up our condition.

If it was a while loop, the statement would read: while 0 < 10

The temp_variable is what we use to reference the individual value of what we’re looping over.

In this variation of the loop, the temp_variable will reference the lower_bound. There is no other way to reference the lower_bound, so it’s stored in the temp_variable.

This may seem redundant at first, but there’s a good reason for it. We can also use a for loop to loop over collections of elements such as an array.

The temp variable will then reference the individual element in that collection or array.

Syntax: for loop on an array/collection
for temp_variable in collection_or_array {

    // use temp_variable to
    // access current element

}
Example: for loop on an array
fn main() {

    let employees = ["John", "Jane", "Jack", "Jill"];

    for x in employees.iter() {

        println!("{}", x);
    }

}

In the example above, we use the .iter() function to iterate over elements in the employees array.

Where previously, the temp_variable referenced the lower_bound, it now references each individual name in the array as the compiler iterates over the array.

We cover arrays in the tutorial Rust Arrays where we cover the for loop again.

Summary: Points to remember

  • Loops allow us to iterate over sections of our code multiple times.
  • The while loop is indefinite and is used when we don’t know specifically how many times a loop should run.
    • We should always have a clear stopping point defined for a while loop, otherwise an infinite loop may occur.
  • The for loop is a definite loop and is used when we know how many times a loop should should run.
    • The for loop can iterate a select number of times defined by the upper bound and lower bound.
    • The for loop can also iterate over arrays and collections.
    • The for loop doesn’t need a counter because the compiler knows beforehand how many times to loop.