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:
ifandmatchare 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.