Frontend Labs
⋯

4. Control flow: everything is an expression

4.1 if, match, and blocks produce values

fn classify(status: u16) -> &'static str {
    // `match` must be EXHAUSTIVE: the `_` arm is required here, because u16 has 65,536 values.
    match status {
        200 | 204 => "success",
        301..=308 => "redirect",
        400..=499 => "client error",
        500..=599 => "server error",
        _ => "unknown",
    }
}

fn main() {
    let n = 7;
    let parity = if n % 2 == 0 { "even" } else { "odd" }; // no ternary; `if` is an expression
    let squared = {
        let t = n * n;
        t + 0 // the last expression, with NO semicolon, is the block's value
    };
    println!("{parity} {squared} {}", classify(404));
}

4.2 Loops: loop, while, for, labels, and break with a value

fn main() {
    // `loop` is an infinite loop that can return a value through `break`.
    let mut attempts = 0;
    let port = loop {
        attempts += 1;
        let candidate = 8000 + attempts;
        if candidate % 3 == 0 {
            break candidate; // the loop's value
        }
    };

    // `for` iterates over anything that implements IntoIterator.
    for i in 0..3 { print!("{i} "); }        // 0 1 2   (0..=3 includes 3)
    for (i, ch) in "héllo".char_indices() { print!("[{i}:{ch}]"); }
    println!();

    // Labels break out of nested loops; no goto needed (compare C §4.2).
    'outer: for row in 0..10 {
        for col in 0..10 {
            if row * col == 42 {
                println!("found at {row},{col}");
                break 'outer;
            }
        }
    }
    println!("port={port} after {attempts} attempts");
}

4.3 if let, let else, and while let

These are shortcuts for a match where you care about one pattern:

fn parse_port(s: &str) -> u16 {
    // let-else: bind on success, or the else block must leave the function (return/break/panic).
    let Ok(port) = s.parse::<u16>() else {
        return 8080;
    };
    port
}

fn main() {
    let maybe_user: Option<&str> = Some("ada");
    if let Some(name) = maybe_user {
        println!("hello {name}");
    }

    let mut stack = vec![1, 2, 3];
    while let Some(top) = stack.pop() { // runs until pop() returns None
        print!("{top} ");
    }
    println!("{} {}", parse_port("443"), parse_port("http"));
}

let else is the Rust version of Go's if err != nil { return } guard clause. It keeps the main path unindented.


Generated from real-life-rust-guide.md · 8 Oct 2026 16:36