Match, if let, While let
Match
Use match
to Branch on a Pattern
The following code demonstrates pattern matching against an enumeration (enum):
//! This example defines different types of US coins using an `enum` and then //! uses a `match` expression to determine the value of a given coin in cents, //! demonstrating how `match` can handle different `enum` variants and extract //! data associated with them. /// Define an `enum`. /// Each variant represents a type of US coin. enum Coin { Penny, Nickel, Dime, /// The `Quarter` is a tuple variant. /// Its field stores the name of a US State. Quarter(String), } /// Returns the value in cents of a given coin. fn value_in_cents(coin: Coin) -> u8 { // The match expression takes a value and compares it against a series of // patterns. Each pattern represents a possible structure or value that the // input value might have. It's similar to a 'switch' statement in other // languages, but it's far more versatile. match coin { // If the coin is a Penny, return 1 cent. Coin::Penny => 1, // If the coin is a Nickel, return 5 cents. Coin::Nickel => 5, // If the coin is a Dime, return 10 cents. Coin::Dime => 10, // If the coin is a Quarter, which contains a state string, the `state` identifier is assigned the value of the field in the enum variant. Coin::Quarter(state) => { // The above is a pattern binding. println!("State quarter from {:?}!", state); 25 } // Rust's match expressions are exhaustive. This means that you must cover all possible cases. // If needed, you can use a catchall: //_ => unreachable!(), } } fn main() { println!("{}", value_in_cents(Coin::Penny)); }
This examples shows pattern matching using a struct
:
// Define a struct named `Point` with three fields: x, y, and z, all of type // i32. This struct will be used for pattern matching in the match expression. struct Point { x: i32, y: i32, z: i32, } // The main function where the example code resides. fn main() { // Create an instance of the `Point` struct. let origin = Point { x: 0, y: 0, z: 0 }; // Use a match expression to perform pattern matching on the origin `Point`. match origin { // This pattern matches any `Point` struct. // It binds the value of the x field to a variable named x. // The .. syntax means "ignore the other fields". // In this case, y and z are ignored. Point { x, .. } => println!("x is {}", x), } }
Patterns accept 1 | 2
for or, 1..=5
for inclusive range, if x % 2 == 0
guards, @-binding Message::Hello { id: id_variable @ 3..=7,}
.
if let
if let
is a concise way to handle a single pattern in a match
expression.
/// The `if let` syntax allows you to combine `if` and `let` /// to handle values that match a specific pattern, while ignoring others. fn main() { // `config_max` is an `Option<u8>` let config_max = Some(3u8); // If `config_max` is `Some`, bind the inner value to `max` if let Some(max) = config_max { // `max` is available here println!("The maximum is configured to be {}", max); } }
while let
while let
is similar to if let
, but it allows you to loop as long as the pattern continues to match.
fn main() { let mut stack = vec![1, 2, 3]; // `while let` is a control flow construct that allows you to run a loop as // long as a pattern matches. We remove the last element of the vector // at each iteration, until the vector is empty and `pop` returns `None`, // which stops the loop. while let Some(top) = stack.pop() { println!("{}", top); } }
See Also
- Control Flow.
- Error Handling.
- Option.
- Result.
- Rust Patterns.