:#/ GSLF Journal
← :#/ GSLF Journal

Rustlers Atom 1.5 - Flow Control

On this page

<figure class="video" style="margin:0;">
<div style="position:relative;width:100%;padding-bottom:56.25%;height:0;overflow:hidden;">
<iframe src="https://www.youtube.com/embed/cF_NrDEir60?si=-fTbuTjTAh-b39ty"
title="YouTube video player"
style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>
</div>
</figure>

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.