在Rust中常常用到模式匹配, match表达式是模式匹配最经常使用的表达式.html
match表达式大体分为3部分, match关键字, head表达式, match块. 这篇主要讨论head表达式怎么写.express
咱们知道, Rust中的表达式只有两种: 位置表达式
, 值表达式
. 相似地, Rust表达式上下文也包括位置表达式上下文
, 值表达式上下文
. head表达式的位置属于位置表达式上下文, 能够是位置表达式或值表达式, 且表现出来的行为不一样.bash
若是是值表达式, 则会对该表达式求值后, 将结果放到一个临时位置, 而后按照match分支的顺序, 比较是否有符合要求的分支. 第一个匹配到的分支做为模式匹配的目标分支, 刚刚建立的临时变量能够在分支内使用.ui
match 5+3 {
8 => println!("equals!"),
_ => println!("not equals!"),
}
复制代码
若是head表达式是位置表达式, 则不会分配临时变量, 而是建立一个绑定, 根据类型是否实现Copy决定是复制语义仍是移动语义.spa
let x = 1;
match x {
1 => println!("one"),
_ => println!("something else"),
}
复制代码
这里的x是位置表达式, 所以整段代码至关于以下这样:code
let x = 1;
let b = x; // 这里由于x是i32, 实现了Copy, 所以是复制语义
match b {
1 => println!("one"),
_ => println!("something else"),
}
复制代码
若是是移动语义, 则会转移变量的全部权到match表达式, 当match表达式结束后, 变量就被销毁了.htm
若是不但愿转移全部权, 则可使用ref或ref mut, 声明一个引用绑定, 按引用进行匹配:get
let x = 1;
match ref x {
&1 => println!("one"),
_ => println!("something else"),
}
复制代码
这段代码至关于:string
let x = 1;
let b = &x;
match b {
&1 => println!("one"),
_ => println!("something else"),
}
复制代码
这里再提一些我本身理解起来比较困难的点: 当head表达式中匹配的是解引用表达式时, 与匹配引用其实是等价的.io
let y = match *x { 0 => "zero", _ => "some" };
let z = match x { &0 => "zero", _ => "some" };
assert_eq!(y, z);
复制代码