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 Option
s and Result
s. In the
code below, we have two Option
s and two Result
s. 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) { }