#rust #pattern-mach
nested or-patterns #
https://blog.rust-lang.org/inside-rust/2020/03/04/recent-future-pattern-matching-improvements.html
Essentially,
|
isn’t a special syntax for match statements but actually a kind of operator used in all pattern matching contexts
// instead of this
match value {
Some(2) | Some(3) | Some(5) | Some(7) => println!("prime"),
Some(0) | Some(1) | Some(4) | Some(9) => println!("square"),
None => println!("nothing"),
_ => println!("something else"),
}
// try this, 可以直接在 constructor 内部解构
match value {
Some(2 | 3 | 5 | 7) => println!("prime"),
Some(0 | 1 | 4 | 9) => println!("square"),
None => println!("nothing"),
_ => println!("something else"),
}
// 同样应用于 if-let
if let Some("fn" | "let" | "if") = token {
println!("keyword");
}
// 多个值,不是 tuple
match vec {
(0, 0) => println!("here"),
(-1 | 0 | 1, -1 | 0 | 1) => println!("close"),
_ => println!("far away"),
}
// guard 例子
// guard 是 match 有,if-let 等没有的
match opt {
Some(x) if x % 2 == 0 => "even",
Some(_odd) => "odd",
None => "nothing",
}
// matches!(expr, pattern) -> bool
#[test]
fn test_matches_macro() {
assert!(matches!("23".parse::<u8>(), Ok(_)));
assert!(!matches!("23".parse::<u8>(), Ok(24)));
assert!(matches!("a23".parse::<u8>(), Err(_)));
}
// binding
match value {
Some(p @ 2 | 3 | 5 | 7) => println!("{p} is a prime"),
Some(sq @ 0 | 1 | 4 | 9) => println!("{sq} is a square"),
None => println!("nothing"),
Some(n) => println!("{n} is something else"),
}
//
let (Ok(i) | Err(i)) = [1, 2, 3].binary_search(&2);
// binary_search
// 这个语法上是可以的,但是没什么用
// 只能是 Result<i32, i32>, 两个类型必须相同
// elixir 在这个事情上做得更好
fn f((Ok(i) | Err(i)): Result<i32, i32>) {}
let some_value = 3;
if let 1 | 2 | 3 = some_value {
println!("asfasdf");
}
//
enum Num {
variant1(u32),
variant2(u32),
}
match num {
variant1(inner) | variant2(inner) => {
println!("{inner}");
}
}
//
enum MusicInfo {
Artist { name: String },
Album { title: String },
}
fn main() {
let artist = MusicInfo::Artist { name: "Keith Jarrett".into() };
let album = MusicInfo::Album { title: "The Köln Concert".into() };
let music_info = if rand::random() { artist } else { album };
let (MusicInfo::Artist { name } | MusicInfo::Album { title: name }) = music_info;
println!("{name}")
}