Control Flow
Control flow allows your program to make decisions and repeat actions.
If Expressions
Basic If
fn main() {
let number = 7;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
Python comparison:
# Python uses indentation instead of braces
number = 7
if number < 5:
print("condition was true")
else:
print("condition was false")
Key differences:
- Rust: No parentheses needed around condition
- Rust: Must use braces
{} - Python: Uses colons
:and indentation - Rust: Condition must be a
bool(no truthy/falsy values)
Else If
fn main() {
let number = 6;
if number % 4 == 0 {
println!("divisible by 4");
} else if number % 3 == 0 {
println!("divisible by 3");
} else if number % 2 == 0 {
println!("divisible by 2");
} else {
println!("not divisible by 4, 3, or 2");
}
}
If as Expression
if is an expression in Rust and can return a value:
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {}", number);
}
Python comparison:
# Python's ternary operator
condition = True
number = 5 if condition else 6
Both branches must return the same type:
let number = if condition { 5 } else { "six" }; // ERROR: type mismatch
Loops
Rust has three kinds of loops: loop, while, and for.
The loop Keyword
Infinite loop:
fn main() {
loop {
println!("again!");
break; // Exit the loop
}
}
Returning Values from Loops
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // Return value from loop
}
};
println!("The result is {}", result); // 20
}
Loop Labels
Disambiguate between nested loops:
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {}", count);
let mut remaining = 10;
loop {
println!("remaining = {}", remaining);
if remaining == 9 {
break; // Break inner loop
}
if count == 2 {
break 'counting_up; // Break outer loop
}
remaining -= 1;
}
count += 1;
}
println!("End count = {}", count);
}
While Loops
Conditional looping:
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("LIFTOFF!!!");
}
For Loops
Iterate over collections:
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {}", element);
}
}
Range
fn main() {
// 1 to 4 (exclusive end)
for number in 1..5 {
println!("{}", number);
}
// 1 to 5 (inclusive end)
for number in 1..=5 {
println!("{}", number);
}
// Reverse
for number in (1..4).rev() {
println!("{}", number);
}
}
Iterating with Index
fn main() {
let a = [10, 20, 30, 40, 50];
for (index, value) in a.iter().enumerate() {
println!("a[{}] = {}", index, value);
}
}
Pattern Matching
The match Expression
fn main() {
let number = 3;
match number {
1 => println!("One!"),
2 => println!("Two!"),
3 => println!("Three!"),
4 => println!("Four!"),
5 => println!("Five!"),
_ => println!("Something else"), // _ is catch-all
}
}
Match with Values
fn value_in_cents(coin: &str) -> u32 {
match coin {
"penny" => 1,
"nickel" => 5,
"dime" => 10,
"quarter" => 25,
_ => 0,
}
}
fn main() {
println!("Value: {}", value_in_cents("dime"));
}
Match Must Be Exhaustive
fn main() {
let number = 3;
// ERROR: non-exhaustive patterns
match number {
1 => println!("one"),
2 => println!("two"),
} // Missing other cases!
}
Fix: Add _ catch-all or handle all cases.
Multiple Patterns
fn main() {
let number = 2;
match number {
1 | 2 => println!("one or two"),
3 | 4 | 5 => println!("three, four, or five"),
_ => println!("something else"),
}
}
Range Patterns
fn main() {
let number = 5;
match number {
1..=5 => println!("one through five"),
6..=10 => println!("six through ten"),
_ => println!("something else"),
}
}
Matching Tuples
fn main() {
let point = (0, 5);
match point {
(0, 0) => println!("origin"),
(0, y) => println!("on y-axis at {}", y),
(x, 0) => println!("on x-axis at {}", x),
(x, y) => println!("point at ({}, {})", x, y),
}
}
Match Guards
Additional conditions:
fn main() {
let num = Some(4);
match num {
Some(x) if x < 5 => println!("less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
}
If Let
Concise way to match one pattern:
fn main() {
let some_u8_value = Some(3);
// Using match
match some_u8_value {
Some(3) => println!("three"),
_ => (),
}
// Using if let (more concise)
if let Some(3) = some_u8_value {
println!("three");
}
}
If Let with Else
fn main() {
let some_value = Some(7);
if let Some(7) = some_value {
println!("lucky seven!");
} else {
println!("not seven");
}
}
While Let
fn main() {
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top);
}
}
Common Patterns
Checking Multiple Conditions
fn classify_number(n: i32) {
match (n > 0, n % 2 == 0) {
(true, true) => println!("positive and even"),
(true, false) => println!("positive and odd"),
(false, true) => println!("negative or zero and even"),
(false, false) => println!("negative or zero and odd"),
}
}
Early Returns
fn process_number(n: i32) -> i32 {
if n < 0 {
return 0;
}
if n > 100 {
return 100;
}
n * 2
}
Loop with Conditional Break
fn find_first_even(numbers: &[i32]) -> Option<i32> {
for &num in numbers {
if num % 2 == 0 {
return Some(num);
}
}
None
}
Practice Exercises
Exercise 1: FizzBuzz
Print numbers 1 to 100:
- "Fizz" for multiples of 3
- "Buzz" for multiples of 5
- "FizzBuzz" for multiples of both
- The number otherwise
fn main() {
for n in 1..=100 {
// Your code here
}
}
Exercise 2: Find Maximum
Write a function that finds the maximum value in a slice:
fn find_max(numbers: &[i32]) -> Option<i32> {
// Return None if empty
// Your code here
}
Exercise 3: Temperature Category
Write a function that categorizes temperature:
- "Freezing" < 0°C
- "Cold" 0-10°C
- "Mild" 11-20°C
- "Warm" 21-30°C
- "Hot" > 30°C
Key Takeaways
- if is an expression that returns a value
- loop creates infinite loops, use
breakto exit - while loops while condition is true
- for is best for iterating over collections
- match must be exhaustive and handles all patterns
- if let is concise for matching single patterns
- Loop labels disambiguate nested loops
Next Steps
In the next chapter, we'll explore functions in depth, including closures and methods.
Quick Reference
// If expression
let x = if condition { 5 } else { 6 };
// Loop with return
let result = loop {
break value;
};
// While loop
while condition {
// code
}
// For loop
for item in collection {
// code
}
// Range
for i in 0..10 { } // 0 to 9
for i in 0..=10 { } // 0 to 10
// Match
match value {
pattern1 => result1,
pattern2 => result2,
_ => default,
}
// If let
if let Some(x) = option {
// use x
}