OSRust.005: Control Flow — if, loop, while, for, break, continue, and Labels

Unique cinematic sci-fi rail-yard illustration representing Rust control flow with loops, branches, and directional paths.

Elementary Overview

Control flow decides which code runs and how many times it runs. Rust provides conditional expressions with if, an unconditional loop, condition-controlled while loops, iterator-driven for loops, and explicit flow controls such as break and continue. Rust also adds two particularly useful features: loops can be labeled, and a loop can return a value through break value;.

This lesson continues directly from OSRust.004: Functions, Parameters, Expressions, and Return Values. It also relies on the type system introduced in OSRust.003: Scalar and Compound Data Types and the mutable bindings introduced in OSRust.002: Variables.

Francesco Ciulla demonstrates Rust control flow with if, match, loop, while, for, and a FizzBuzz exercise.

if Is an Expression

In Rust, if is an expression rather than only a statement. That means it can choose a value that becomes part of a larger expression. Its condition must evaluate to bool; Rust does not automatically convert integers or pointers into Boolean truth values.

fn main() {
    let temperature = 78;

    if temperature > 85 {
        println!("hot");
    } else if temperature > 70 {
        println!("normal");
    } else {
        println!("cool");
    }
}

The official Rust Programming Language control-flow chapter emphasizes that every branch of an if expression used to produce a value must have compatible types.

let online = true;
let status = if online { "ready" } else { "offline" };

println!("{status}");

loop Repeats Until You Stop It

The loop keyword starts an unconditional loop. Unlike while, there is no condition at the top. Execution repeats until code inside the loop exits with break, returns from the function, panics, or otherwise terminates execution.

fn main() {
    let mut count = 0;

    loop {
        count += 1;
        println!("count = {count}");

        if count == 3 {
            break;
        }
    }
}
Trevor Sullivan walks through Rust conditionals and loop forms in a practical terminal-driven tutorial.

A loop Can Return a Value

Rust lets break carry a value out of a loop. This makes a loop useful when the program must repeat work until it computes a final result.

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("result = {result}");
}

This works because loop itself is an expression. The value supplied to break becomes the value of that expression.

Rust community discussion highlights practical uses of unconditional loops, break values, and labeled loops.

continue Skips to the Next Iteration

continue stops the current iteration immediately and begins the next one. It is useful when some values should be ignored without ending the entire loop.

fn main() {
    for number in 1..=6 {
        if number == 3 {
            continue;
        }

        println!("{number}");
    }
}

while Runs While a Condition Is True

A while loop is appropriate when repetition depends on a Boolean condition that can be checked before each iteration.

fn main() {
    let mut number = 3;

    while number != 0 {
        println!("{number}!");
        number -= 1;
    }

    println!("LIFTOFF!");
}
dcode focuses specifically on Rust while loops and condition-controlled repetition.

for Iterates Over Values

for is usually the clearest loop when iterating through a collection or range. It works through Rust’s iterator system, so the loop receives each item without requiring manual index bookkeeping.

fn main() {
    let watts = [1200, 1250, 1300, 1275];

    for value in watts {
        println!("{value} W");
    }
}

Ranges make counted loops concise. 1..5 excludes 5, while 1..=5 includes it.

for rack in 1..=4 {
    println!("checking rack {rack}");
}

Labels Control Nested Loops

Nested loops can be labeled with a leading apostrophe. A labeled break or continue can then target an outer loop directly instead of only the innermost loop.

fn main() {
    'outer: for rack in 1..=3 {
        for slot in 1..=4 {
            if rack == 2 && slot == 3 {
                break 'outer;
            }

            println!("rack {rack}, slot {slot}");
        }
    }
}

Labels are especially useful when multiple nested control-flow levels would otherwise require extra state variables. Use them deliberately; clear loop names are easier to follow than deeply nested unlabeled exits.

Choosing the Right Loop

  • Use loop when repetition is intentionally open-ended or the exit conditions occur inside the body.
  • Use while when a Boolean condition naturally controls whether another iteration should begin.
  • Use for when iterating through a collection, iterator, or numeric range.
  • Use break to exit and continue to skip the rest of the current iteration.
  • Use labels when nested loops need an explicit outer target.

Compile and Run

cargo new control_flow_lab
cd control_flow_lab
cargo run

Replace src/main.rs with one example at a time. Compile after every change and observe how Rust’s type checker responds when an if condition is not Boolean or when branch result types do not match.

Mini Lab

  1. Create a variable named temperature and classify it as cool, normal, or hot with if/else if/else.
  2. Create a loop that increments a counter and returns the value 100 with break 100;.
  3. Write a while countdown from 5 to 1.
  4. Use for to iterate through an array of four power readings.
  5. Use continue to skip one reading.
  6. Create two nested loops and use a label to exit the outer loop.
  7. Rewrite one while loop as a for loop where appropriate and explain which version is clearer.

Knowledge Check

  1. What type must an if condition evaluate to?
  2. Why can if be assigned directly to a variable?
  3. What is the normal way to exit an unconditional loop?
  4. What special feature allows a loop to produce a value?
  5. When is while a good choice?
  6. Why is for usually preferred when iterating a collection?
  7. What does continue do?
  8. What problem do loop labels solve?
  9. What is the difference between 1..5 and 1..=5?

Answers

  1. bool.
  2. Because if is an expression in Rust and can evaluate to a value.
  3. Use break, return from the function, or otherwise terminate execution.
  4. break value; supplies the loop expression’s result.
  5. When a Boolean condition naturally determines whether another iteration should begin.
  6. It uses the iterator system directly and avoids manual index management.
  7. It skips the rest of the current iteration and starts the next one.
  8. They let break or continue target a specific enclosing loop.
  9. 1..5 excludes 5; 1..=5 includes 5.

Primary References

Elementary Review

Rust control flow is built around expressions and explicit intent. if chooses paths, loop repeats until explicitly stopped, while repeats while a Boolean remains true, and for iterates through values. break, continue, return values from loop, and labels give precise control without resorting to unstructured jumps.

BitcoinVersus.Tech Editor’s Note:
We volunteer daily to ensure the credibility of the information on this platform is Verifiably True. If you would like to support to help further secure the integrity of our research initiatives, please donate using the QR code provided

Bitcoin donation QR code for 5,000 sats.

For best QR-code scanning results, please scan this donation code from a desktop or larger screen. Mobile screens may prevent camera recognition.

Leave a Reply