Skip to content

Rust If...Else

if lets your program make decisions — run one block of code or another, depending on a condition.

fn main() {
let age = 20;
if age >= 18 {
println!("You can vote");
}
}
▶ Try it Yourself

A couple of things to notice, since they trip people up coming from other languages:

  • No parentheses around the condition — if age >= 18, not if (age >= 18).
  • The condition must be a real bool. if age (a number) won’t compile — you need if age != 0 or similar.
fn main() {
let age = 15;
if age >= 18 {
println!("You can vote");
} else {
println!("Not old enough yet");
}
}
▶ Try it Yourself
fn main() {
let score = 72;
if score >= 90 {
println!("Grade: A");
} else if score >= 75 {
println!("Grade: B");
} else if score >= 60 {
println!("Grade: C");
} else {
println!("Grade: F");
}
}
▶ Try it Yourself

Rust checks each condition top to bottom and runs the first one that matches, just like you’d expect.

Here’s something Rust does that a lot of languages don’t: if can produce a value. That means you can use it on the right side of a let:

fn main() {
let age = 20;
let status = if age >= 18 { "adult" } else { "minor" };
println!("{status}");
}
▶ Try it Yourself

This works the same way returning a value from a function does — no semicolon after the value in each branch. The one requirement: both branches must produce the same type (here, both are &str).

You can put an if inside another if. That works, but two or three levels deep it gets hard to read. Often you can join the conditions with the logical operators && (and) and || (or) instead:

fn main() {
let temperature = 22;
let is_raining = false;
// Nested: works, but drifts to the right
if temperature > 15 {
if !is_raining {
println!("Nested: go for a walk");
}
}
// The same check as one condition
if temperature > 15 && !is_raining {
println!("Combined: go for a walk");
}
// || is true if either side is true
if temperature < 0 || temperature > 35 {
println!("Stay inside");
} else {
println!("The weather is fine");
}
}

Output:

Nested: go for a walk
Combined: go for a walk
The weather is fine
▶ Try it Yourself

Nesting still makes sense when the inner block does something extra, or when it has its own else. But when the only point of the outer if is to guard the inner one, && says the same thing more simply. To check that a number is inside a range, write temperature >= 15 && temperature <= 25. Rust doesn’t allow 15 <= temperature <= 25.

Store a number n = 7. Use if as an expression to set a variable kind to "even" or "odd", then print 7 is odd. Hint: a number is even when n % 2 == 0.

Show solution
fn main() {
let n = 7;
let kind = if n % 2 == 0 { "even" } else { "odd" };
println!("{n} is {kind}");
}

Output:

7 is odd
▶ Try it Yourself

A cinema charges 5 dollars for children under 12, 7 for people 65 or older, and 12 for everyone else. Store an age of 70, work out the price with one if / else if / else expression, and print Ticket: $7. Hint: every branch must give back a number, and the whole if ends with a semicolon after the last }.

Show solution
fn main() {
let age = 70;
let price = if age < 12 {
5
} else if age >= 65 {
7
} else {
12
};
println!("Ticket: ${price}");
}

Output:

Ticket: $7
▶ Try it Yourself
  • if condition { ... } — no parentheses needed; the condition must be a bool.
  • Chain more checks with else if, and fall back with else.
  • Join conditions with && and || instead of nesting if inside if.
  • if can be used as an expression to produce a value — both branches must match in type, and you need an else.

Quick check

1. Which of these is required for a Rust if condition?

2. When using if as an expression with let, what's required of both branches?

Score: 0 / 2