kota's memex

if

let number = 3;

if number < 5 {
    println!("condition was true");
} else {
    println!("condition was false");
}

There's also else if which works as you'd expect. Since if is an expression we can use it like this in a let statement:

let number = if condition { 5 } else { 6 };

However, all arms must evaluate to the same type or you will get a compile error.

if let

The if let syntax allows you to combine if and let and is often used instead of a match statement when you only want to do something with a single outcome:

let number = Some(7);
if let Some(i) = number {
    println!("Matched {:?}!", i);
}

loops

Rust has three kinds of loops: loop, while, and for.

loop

The loop keyword tells rust to execute a block of code over and over again forever or until you tell it to break.

let mut counter = 0;

let result = loop {
    counter += 1;

    if counter == 10 {
        break counter * 2;
    }
};

labels

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;

        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!("final count = {count}");
}

while

The while keyword evaluates a condition on each iteration of the loop and when the condition is false it will automatically call break:

let mut number = 3;

while number != 0 {
    println!("{number}");
    number -= 1;
}

for

For loops offer a more convenient syntax for looping through the elements of a collection compared to a while loop.

let a = [10, 20, 30, 40, 50];

for element in a {
    println!("value = {element}");
}

for reference

You may take a reference to the elements rather than a copy:

let number_list = vec![34, 50, 25, 100, 65];
let mut largest = &number_list[0];

for number in &number_list {
    if number > largest {
        largest = number;
    }
}

match

The match control flow construct allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things.

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

Match patterns must be exhaustive. Sometimes it's useful to create a catch-all pattern. This can be done easily by giving a new variable name as the pattern. A common choice is other or _ to discard the value:

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    other => move_player(other),
}