In this video I give an overview over the matching capabilities in Rust.
#[derive(Debug)]
enum X {
A,
B(i64),
C(String),
}
#[derive(Debug)]
struct S {
pub name : String,
pub age : u16,
}
fn main() {
let args : Vec<String> = std::env::args().collect();
// match expression on literals or with a variable:
let x : X = match args.len() {
2 => X::C(args[1].clone()),
0 | 1 => X::A,
l => X::B(l as i64),
};
println!("{x:?}");
// match statement to destruct enum:
match x {
X::A => {
println!("Empty A");
},
X::B(n) => {
println!("Multiple arguments: {}", n);
},
X::C(s) => {
println!("Exactly one argument: {}", s);
},
};
// matching to destruct tuple:
let t : (i64, String) = (17, "abc".to_string());
match &t {
(i, s) => {
println!("A number {i} and a string {s}.");
},
};
// Or:
let (i,s) = t; // matching in `let` statements
println!("i={i} s={s}");
// matching to destruct an array:
let a : [u64; 3] = [2, 3, 5];
let [x, y, z] = a;
println!("x={x} y={y} z={z}");
// matching to destruct a struct:
let s = S{name:"Karl".to_string(), age: 55};
let S{name: n, age: a} = &s;
println!("name={n} age={a}");
}
#[derive(Debug)]
enum X {
A,
B(i64),
C(String),
}
#[derive(Debug)]
struct S {
pub name : String,
pub age : u16,
}
fn f(S{name: _, age: a} : &S) -> u16 {
println!("f called with age {a}");
a+1
}
fn main() {
let args : Vec<String> = std::env::args().collect();
// match expression on literals or with a variable:
let x : X = match args.len() {
2 => X::C(args[1].clone()),
0 | 1 => X::A,
l => X::B(l as i64),
};
println!("{x:?}");
// if let:
if let X::C(s) = x {
println!("String case: {s}");
}
// while let:
let mut stack = Vec::new();
stack.push("A1");
stack.push("B2");
stack.push("C3");
while let Some(top) = stack.pop() {
println!("{}", top);
}
// for loops:
let v = vec!["aaa", "bbb", "ccc"];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
}
// let statements:
let s = S{name: "Max".to_string(), age: 54};
let S{name:m, age:_} = s;
println!("Name: {m}");
let i = 1;
let j = 2;
let (j, i) = (i, j);
println!("i={i} j={j}");
// function arguments:
let s = S{name: "Max".to_string(), age: 54};
println!("One more: {}", f(&s));
}
A pattern can be "refutable" or "irrefutable". An irrefutable pattern
matches always, given an object of a certain type. A refutable pattern
can be rejected. In certain contexts only irrefutable patterns are allowed
(function arguments, let
statements, etc.), in other contexts refutable
patterns are allowed and can then control the flow of execution (match
expressions, if let
statements, while let
statements, etc.).
- Rust book: https://doc.rust-lang.org/book/ch18-00-patterns.html
- Rust reference: https://doc.rust-lang.org/reference/patterns.html
- Rust by example: https://doc.rust-lang.org/rust-by-example/flow_control/match.html
- Video: https://youtu.be/NaK4dxlTUJU
- Overview: https://gist.github.com/max-itzpapalotl/18f7675a60f6f9603250367bcb63992e