if let Bindings
The first concept is if let bindings, which you can read about
here. This control flow construct
allows us to check if the value of an expression matches some pattern, and bind it to
a new variable if so. We can have an else branch on this if let statement as well.
We can check out a brief demo of this pattern on both Options and Results. In the
code below, we have two Options and two Results. The first option is None, while
the second is Some(T) (where T is String in this case). We can pattern match both
of these variables using if let to bind them to a new variable if they match the
pattern (Some(_)) that we are checking for. Notice in the first check, we bind x to
a new variable x, and in the second we bind x to a new variable e. We can do the
same for Result.
fn main() { let x: Option<String> = None; let y: Option<String> = Some("Hello, World!".to_string()); if let Some(x) = x { println!("x is some: {}!", x); } else { println!("x is none"); } if let Some(e) = y { println!("y is some: {}!", e); } else { println!("y is none"); } let w: Result<String, String> = Err("There was something wrong...".into()); let z: Result<String, String> = Ok("Hello, World!".to_string()); if let Ok(z) = z { println!("z was ok: {}!", z); } else { println!("z was not ok"); } if let Err(e) = w { println!("w was err: {}!", e); } else { println!("w was ok"); } }
In the first check in our code, we checked if rest is Some (Option<T> values
in rust are either Some(T) or None). If so, we bind it to a new variable (also
called rest, there is no need to choose a new name, this newly bound variable has a
smaller scope). We use the if let pattern again, to check if we have at least 2
characters at the beginning of rest:
#![allow(unused)] fn main() { if let Some(rest) = rest { if let Some(&[first, second]) = rest.get(0..2) { }