Back to Blog

[Rust] Control Flow: Mastering If Expressions and Loops

In programming, the ability to run code based on specific conditions or to repeat execution while a condition is met is fundamental. Rust provides several constructs to control the flow of your program, primarily if expressions and various types of loops.


1. if Expressions

An if expression allows you to branch your code depending on conditions. You provide a condition and tell the program: "If this condition is met, run this block; otherwise, don't."

Basic Usage

The most common form is combining if and else.

Rust
fn main() {
    let number = 3;

    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}
  • Condition: The condition (e.g., number < 5) must evaluate to a boolean (bool).
  • Arms: The blocks of code associated with conditions (inside {}) are often called 'arms'.
  • Strict Typing: Unlike languages like JavaScript or Ruby, Rust will not automatically try to convert non-Boolean types to a Boolean. Using a number directly in an if statement (e.g., if number { ... }) will result in a compilation error. You must be explicit, such as if number != 0.

Handling Multiple Conditions with else if

You can use else if to check multiple conditions in sequence.

Rust
fn main() {
    let number = 6;

    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else {
        println!("number is not divisible by 4 or 3");
    }
}

Note: Rust executes only the first block where the condition is true. Once it finds one, it skips the rest. If you have too many conditions, consider using the match construct for better readability.

Using if in a let Statement

Since if is an expression, it returns a value. This allows you to use it on the right side of a let statement.

Rust
fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };

    println!("The value of number is: {number}");
}
  • Type Compatibility: Crucially, the values returned from every arm of the if must be of the same type. You cannot return an integer in one arm and a string in another.

2. Repetition with Loops

Rust provides three kinds of loops: loop, while, and for.

The infinite loop

The loop keyword tells Rust to execute a block of code over and over again until you explicitly tell it to stop.

Rust
fn main() {
    loop {
        println!("again!");
        break; // Use the break keyword to exit the loop.
    }
}

Returning Values from Loops

You can pass the result of an operation out of a loop by adding the value you want to return after the break expression.

Rust
fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    println!("The result is {result}"); // Prints 20
}

Loop Labels

When dealing with nested loops, break and continue apply to the innermost loop. You can use loop labels (starting with a single quote ') to specify which loop you want to exit.

Rust
fn main() {
    let mut count = 0;
    'counting_up: loop {
        let mut remaining = 10;
        loop {
            if remaining == 9 { break; } // Exits the inner loop
            if count == 2 { break 'counting_up; } // Exits the outer loop
            remaining -= 1;
        }
        count += 1;
    }
}

Conditional Loops with while

The while loop runs as long as a condition remains true.

Rust
fn main() {
    let mut number = 3;
    while number != 0 {
        println!("{number}!");
        number -= 1;
    }
    println!("LIFTOFF!!!");
}

Looping Through a Collection with for

For safety and efficiency, for is the most recommended way to iterate over collections like arrays.

Rust
fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a {
        println!("the value is: {element}");
    }
}
  • Safety: Using for eliminates the risk of "index out of bounds" errors that might occur with while loops and manual indexing.
  • Ranges: To run code a certain number of times, use a Range like (1..4). You can also use .rev() to reverse the sequence.

Summary

  1. if: Used for branching. Must have a bool condition and can be used as an expression.
  2. loop: Infinite repetition. Useful for retrying operations and returning values via break.
  3. while: Repeats code while a condition is true.
  4. for: The most common and safest way to iterate over collections or ranges.

Comments