Rustlers Atom 1.5 - Flow Control

Rust’s control flow is an extension of its expression-oriented design: every conditional and pattern match produces a value.

if

Unlike in C or Python, if returns always a value. The branches must evaluate to the same type.

fn main() {
    let temperature = 25;
    let weather = if temperature > 30 {
        "hot"
    } else if temperature < 10 {
        "cold"
    } else {
        "mild"
    };

    println!("The weather is {}", weather);
}

Here, the entire if block yields a value that gets bound to weather. Every branch must produce a compatible type; mixing strings and numbers, for example, would fail to compile. Rust uses this rule to eliminate runtime ambiguity, what you see is what you get.

match

match is Rust’s exhaustive pattern-matching tool. The compiler ensures every possible input is handled, so it's very different from the switch expression of many other programming languages.

fn main() {
    let code = 404;

    let message = match code {
        200 => "OK",
        404 => "Not Found",
        500 => "Internal Server Error",
        _ => "Unknown", // the wildcard pattern
    };

    println!("Response: {}", message);
}

Each arm is an expression, and like if, match itself returns a value.

The _ pattern acts as a catch-all, and the compiler enforces its necessity if the match is non-exhaustive.

Patterns can bind variables and destructure data directly inside a match.

This is how Rust turns control flow into a tool for data decomposition.

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Echo(String),
}

fn process(msg: Message) {
    match msg {
        Message::Quit => println!("Exiting program."),
        Message::Move { x, y } => println!("Moving to ({}, {})", x, y),
        Message::Echo(text) => println!("Echo: {}", text),
    }
}

fn main() {
    process(Message::Move { x: 10, y: 20 });
}

if let

When you only care about one pattern and want to ignore all others, if let is a concise variant of match.

fn main() {
    let maybe_number = Some(42);

    if let Some(n) = maybe_number {
        println!("The number is {}", n);
    } else {
        println!("No number found");
    }
}

It’s sugar for a single match arm with an implicit _ => {} for everything else.

Takeaway

Rust’s flow control unifies logic and structure:

  • if and match are both expressions — they yield values.
  • Exhaustiveness is guaranteed by the compiler.
  • Patterns can bind, destructure, and filter simultaneously.
  • Control flow becomes a type-safe decision tree, not a maze of runtime conditions.

You'll only receive email when they publish something new.

More from GSLF
All posts