Step 1 of 5 · Reading · ~4 min
Learn
Control Flow
If Expressions and match
By the end of this lesson you can make a program choose between several outcomes with an if/else if chain or a match, put the most specific case first so it is not shadowed, and use either construct to produce a value.
if: a bool condition, braces, no parentheses
The condition goes straight after if, with no parentheses, and the body must be in braces. The condition must be a real bool: if 1 { } does not compile, because Rust has no "truthy" integers.
let fuel = 12;
if fuel < 10 {
println!("refuel now");
} else if fuel < 25 {
println!("refuel soon");
} else {
println!("fine");
}
// prints: refuel soon
Rust tests the conditions top to bottom and runs the first branch whose condition is true. Every later branch is skipped, even if its condition would also be true.
if is an expression
A block's last expression, written without a semicolon, is the block's value. So an if/else can sit on the right of let, and Rust needs no ?: ternary operator:
let speed = 72;
let verdict = if speed > 70 { "ticket" } else { "ok" };
println!("{}", verdict); // ticket
Both branches must produce the same type. if speed > 70 { "ticket" } else { 0 } is a compile error: one branch is a &str, the other an integer.
The ordering trap, on leap years
A year is a leap year if it divides by 4, except centuries, except centuries that divide by 400. The rules overlap, so the order of the checks decides the answer:
let year = 1900;
let wrong = if year % 4 == 0 { "leap" } // 1900 % 4 == 0: stops here
else if year % 100 == 0 { "common" }
else { "common" };
let right = if year % 400 == 0 { "leap" } // most specific rule first
else if year % 100 == 0 { "common" }
else if year % 4 == 0 { "leap" }
else { "common" };
println!("{} {}", wrong, right); // leap common
| year | wrong order | right order |
|---|---|---|
| 2024 | leap | leap |
| 1900 | leap | common |
| 2000 | leap | leap |
Because the first true branch wins, a general test placed above a specific one makes the specific branch unreachable. Put the narrowest condition first.
match: patterns, checked for completeness
match compares one value against patterns, top to bottom, and runs exactly one arm. There is no fallthrough and no break. Like if, it produces a value:
let battery = 57;
let icon = match battery {
0 => "empty",
1..=20 => "low", // ..= is an inclusive range
21..=80 => "ok",
_ => "full", // _ matches anything left over
};
println!("{}", icon); // ok
The compiler demands that the arms cover every possible value. Delete the _ arm above and the build fails with a non-exhaustive patterns error that names the uncovered ranges (the negatives and 81 upward). You cannot forget a case by accident.
You can match two facts at once by putting them in a tuple. With two bools there are exactly four combinations, and the compiler checks that your arms cover all of them:
let weekend = true;
let raining = false;
let plan = match (weekend, raining) {
(true, false) => "hike",
(true, true) => "museum",
(false, _) => "work",
};
println!("{}", plan); // hike
Remainders of negative numbers
The Numbers lesson said integer division truncates toward zero. The remainder follows it: -7 % 3 is -1, not 2, and -9 % 3 is 0. So x % 3 == 0 is the reliable divisibility test for any sign, while x % 3 > 0 as a "not divisible" test is false for -7 and picks the wrong branch.
Common mistakes
- General test first. Checking the 3 rule before the 15 rule makes 15, 30 and 45 print
Fizz: the first true branch wins and theFizzBuzzbranch never runs. - Separate
ifs instead of one chain. Withoutelse, several branches can run, and 15 printsFizzandBuzzon separate lines instead of one line. - Testing
% 3 > 0for "not divisible". Negative remainders are negative, so -7 comes out asFizzinstead of-7. - Forgetting zero.
0 % 3and0 % 5are both0, so 0 isFizzBuzz, not0.
Your exercise
The starter reads one integer n and prints it unchanged. Replace that with a single if/else if chain or a match that prints the right word or the number. The mistake to avoid: a general check placed above the specific one.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…