Rust Book - Chapter 6.3

The if let syntax provides a way to combine if and let into a less verbose way to handle values that match one pattern while ignoring the rest.

The code in the if let block doesn't run if the value doesn't match the pattern.

Using if let means less typing, less indentation, and less boilerplate code. But you lose exhaustive checking that match enforces.

Best way to think of if let is as a syntactic sugar for a match that runs code when the vlaue matches one pattern and then ignores all other values.

The following program uses just one arm of the match pattern, ignoring the rest. This is a good case for if let.

enum Status {
    Active,
    Suspended(),
    Deleted,
}

struct Account {
    id: String,
    status: Status,
}

// good candidate for if ... let expression, as we only care about one pattern, ignoring the rest
fn suspend_account(account: Account) {
    match account.status {
        Status::Active => {
            // proceed to suspend account
            println!("Proceeding to suspened account");
        }
        _ => (), //do nothing
    }
}

fn main() {
    let account = Account {
        id: String::from("C0001"),
        status: Status::Active,
    };
    suspend_account(account);
}

Let's proceed to convert the program to use if let

fn suspend_account(account: Account) {
    if let Status::Active = account.status {
        // proceed to suspend account
    }
}

if let else

We can also have an else block with the if else. This would be equivalent to the catch-all arm _ of the match.

fn suspend_account(account: Account) {                             
    if let Status::Active = account.status {                       
        // proceed to suspend account                              
        println!("proceeding to suspend account");                 
    } else {                                                       
        panic!("Cannot suspend with status {:?}", account.status); 
    }                                                              
}                                                                  
                                                                   
fn main() {                                                        
    let account = Account {                                        
        id: String::from("C0001"),                                 
        status: Status::Deleted,                                   
    };                                                             
    suspend_account(account);                                      
}