Rust中match语句如何结合多模式与条件判断匹配Some(a)或None
你第三种写法编译失败的核心原因是:Rust的match分支语法中,多模式匹配的|只能用来连接多个并列的模式,守卫条件(if开头的部分)是作用于整组模式的独立表达式,不能和模式混写。你把None写在守卫里的|后,会被解析为按位或运算,自然类型不匹配无法编译。
另外要注意,如果多模式中存在绑定变量,要求变量必须出现在所有备选模式中,因此你不能直接写None | Some(b_val) if b_val == a,因为None模式中不存在b_val这个绑定,会触发编译错误。
接下来给你几种符合Rust惯用风格的实现方案:
方案1:抽离重复逻辑的match写法
如果你偏好使用match,只需要把重复的逻辑抽成独立函数即可,没有任何额外开销:
fn main() { let a = 3; let b = Some(5); fn exec_logic() { println!("do something"); } match b { Some(b_val) if b_val == a => exec_logic(), None => exec_logic(), Some(_) => println!("do something else"), } }
方案2:使用Option::map_or(最推荐的通用写法)
Option内置的map_or方法刚好适配你的需求:第一个参数为None时的返回值,第二个参数为Some时对内部值的判断逻辑,不需要担心panic,配合as_ref使用也不会转移所有权:
fn main() { let a = 3; let b = Some(5); // 如果a实现了Copy,可以直接这么写 if b.map_or(true, |val| val == a) { println!("do something"); } else { println!("do something else"); } // 通用写法,适用于所有实现了PartialEq的类型,不会转移a或b的所有权 // if b.as_ref().map_or(true, |val| val == &a) { // println!("do something"); // } else { // println!("do something else"); // } }
方案3:直接利用Option的PartialEq实现
只要A类型实现了PartialEq,Option<A>本身也支持等值比较,写法最简洁直观:
fn main() { let a = 3; let b = Some(5); if b.is_none() || b == Some(a) { println!("do something"); } else { println!("do something else"); } }
另外你写的第二种if b.is_none() || b.unwrap() == a虽然能运行,但非常不推荐:虽然||是短路运算,is_none()为true时不会执行unwrap(),但这种写法容易在后续代码修改时破坏短路逻辑导致panic,完全可以用上面的更安全的写法替代。
内容的提问来源于stack exchange,提问作者thanasis2028
相关产品推荐
相关产品推荐

