Rust track

Lesson 04 · Part 1: Basics

Control Flow

Conditionals, loops and pattern matching with match

Part 1: Basics4 min readFree lesson

Rust's control flow may seem familiar, but it is subtly different from other languages ​​in that it is expression-oriented. if can hold a value, loop can return a value, and for consumes an iterator. If you learn the differences in this episode, all future code will become more natural.

Learning Objectives

  • Use if/else/else if in both sentence and expression forms.
  • The value is returned in the pattern loop break value.
  • Select and use while and for in according to the situation.
  • Exit the nested loop at once using the label loop.

Key concepts

If both branch types of the condition are the same, the entire if can be used as the value.

let label = if score >= 60 { "Pass" } else { "Retest" };

Only bool must be placed in the condition position (there is no integer truthy such as if 0).

let answer = loop {
if condition { break 42; }
};

If you send a value to break, it becomes the evaluation value of the loop expression. Very useful for infinite loop conditional exit patterns.

3) while vs for in

  • while: Repeat as long as the condition is true. When the index changes.
  • for in: Iterator / range (0..n, 0..=n) / traverse arrays, vectors, etc. First of all, if you don't need an index.

If you name the loop with 'label:, you can finish the loop from the inside to the outside with break 'label;.

See as example

//Part 4 Example 1: if·else·else Using if and if as expressions

fn main() {
    let score = 78;

    //Traditional if/else if/else chain
    if score >= 90 {
        println!("A");
    } else if score >= 80 {
        println!("B");
    } else if score >= 70 {
        println!("C");
    } else {
        println!("F");
    }

    //Rust's if is an expression, so it can be used as a value.
    let label = if score >= 60 { "Pass" } else { "Retest" };
    println!("Result: {label}");

    //However, all branches must have the same type.
    //let bad = if true { 1 } else { "Error" }; // ❌ Type mismatch
}
//Part 4 Example 2: The break value of loop and while

fn main() {
    //loop is an infinite loop, but if you send a value to break, it becomes the expression value.
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2; //This value is the result of the loop expression
        }
    };
    println!("loop Result: {result}");

    //while is a condition-based repetition
    let mut n = 3;
    while n > 0 {
        println!("Countdown: {n}");
        n -= 1;
    }
    println!("Fire!");
}
//Part 4 Example 3: for in range/array, and label loop

fn main() {
    //0..5 is 0,1,2,3,4 (excluding the end). 0..=5 is 0~5 (including the end).
    for i in 0..5 {
        println!("i = {i}");
    }

    let arr = ["apple", "banana", "cherry"];
    for fruit in arr.iter() {
        println!("Fruit: {fruit}");
    }

    //If you need an index together, you can use enumerate()
    for (idx, fruit) in arr.iter().enumerate() {
        println!("{idx}: {fruit}");
    }

    //label loop — outer loop break.
    'outer: for x in 0..3 {
        for y in 0..3 {
            if x + y == 3 {
                println!("breaking at ({x},{y})");
                break 'outer;
            }
        }
    }
}

Common Mistakes

A. == is the correct comparison operator. = is an assignment, so it cannot be used in a conditional expression. Additionally, only bool can be placed in place of the if condition, so codes such as if 1 { ... } are not allowed.

A. To include the end, add =, like 0..=n. 0..n excludes the end.

A. If the intent of infinite loop is clear, loop is the standard. loop allows the compiler to perform smarter checks using information called “unfinished loops.” Being able to send values ​​to break is also a privilege unique to loop.

A. Use the label ('outer: for ... { ... break 'outer; }). The intent is clearer than a pattern that checks for boolean flags.

Cleanup

  • if is an expression — if both branch types are the same, it can be used as a value.
  • loop is an infinite loop, and the value can be returned as break value.
  • while is condition-based, and for in is iterator/range traversal.
  • Nested loop escapes are labeled 'name: break 'name;.

Try it yourself

Solve the assignment below. The reference solution is shown below.

Example files

The runnable files used in this lesson. Copy them into your own project and experiment.

src/control_flow/Cargo.tomlTOML
[package]
name = "control_flow"
version = "0.1.0"
edition = "2021"
default-run = "control_flow"

[dependencies]
src/control_flow/src/main.rsRust
fn main() {
    println!("This crate has three running examples.");
    println!();
    println!("  cargo run --bin ex01_if");
    println!("  cargo run --bin ex02_loop_while");
    println!("  cargo run --bin ex03_for");
}

Assignment

Problem 1 — FizzBuzz

  • File name: homework_01/src/main.rs
  • Core concepts: for in range, if/else if/else

Requirements

  • Prints 1 to 15 one line at a time.
  • If it is a multiple of 3, Fizz, if it is a multiple of 5, Buzz, if both, FizzBuzz, otherwise output a number.

Expected output

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

Hint

  • You can check for multiples of 15 first, or use (i % 3 == 0, i % 5 == 0) tuple branching.

  • Note that it is 1..=15, not 0..=15.

  • File name: homework_02/src/main.rs

  • Core concepts: for in array traversal, variable variable update

Requirements

  • The array let nums = [37, 12, 88, 45, 91, 23, 76]; is given.
  • Find the maximum value and print it. Implement directly with the for loop without using methods such as iter().max().

Expected output

Array: [37, 12, 88, 45, 91, 23, 76]
Maximum value: 91

Hint

  • Starts with let mut max = nums[0];.
  • for n in nums.iter() { if *n > max { max = *n; } }.
  • The integer is of type Copy, so you can get the value by dereferencing it as *n (referencing and borrowing are detailed in the next chapter).

Check the correct answer

After solving it yourself, compare it with the reference solution below.

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

homework_01/Cargo.tomlTOML
[package]
name = "homework_01"
version = "0.1.0"
edition = "2021"

[dependencies]
homework_01/src/main.rsRust
//Key points:
//- If you check for multiples of 15 first, the if/else if chain becomes cleaner.
//- All branch result types must be the same to be grouped into an expression, but since it is only output here, you do not need to worry about it.

fn main() {
    for i in 1..=15 {
        if i % 15 == 0 {
            println!("FizzBuzz");
        } else if i % 3 == 0 {
            println!("Fizz");
        } else if i % 5 == 0 {
            println!("Buzz");
        } else {
            println!("{i}");
        }
    }
}
homework_02/Cargo.tomlTOML
[package]
name = "homework_02"
version = "0.1.0"
edition = "2021"

[dependencies]
homework_02/src/main.rsRust
//Key points:
//- Initialize max with the first element and iterate through and update the rest.
//- `for n in nums.iter()` means `n:

fn main() {
    let nums = [37, 12, 88, 45, 91, 23, 76];

    let mut max = nums[0];
    for n in nums.iter() {
        if *n > max {
            max = *n;
        }
    }

    println!("Array: {:?}", nums);
    println!("Maximum value: {max}");
}

Learn this lesson with a mentor

Work through the Rust track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now