关于Rust中variable @ subpattern的技术疑问
关于Rust中
variable @ subpattern的技术疑问 嘿,我最近研究Rust模式匹配的时候,碰到个有点绕的写法,先给你看段官方风格的示例代码:
let x = 2; match x { e @ 1 ..= 5 => println!("got a range element {}", e), _ => println!("anything"), }
当时我就纳闷了——为啥非要多声明一个新变量e啊?直接写成下面这样难道不行吗?
let x = 2; match x { 1 ..= 5 => println!("got a range element {}", x), _ => println!("anything"), }
其实这就是Rust里变量名 @ 子模式语法的妙用,核心就是既匹配指定的子模式,同时把匹配到的值绑定给变量,在很多场景下比直接用外部变量灵活太多,给你唠几个实用场景就懂了:
避开变量遮蔽的坑:要是匹配的上下文里外部变量
x被其他变量遮蔽了,你就没法直接用它了。比如处理枚举这种复杂结构时:enum MyEnum { Number(i32), Text(String), } let val = MyEnum::Number(3); match val { MyEnum::Number(n @ 1..=10) => println!("Got a small number: {}", n), MyEnum::Number(n) => println!("Got a bigger number: {}", n), MyEnum::Text(s) => println!("Got text: {}", s), }这里不用
n @ 1..=10的话,你要拿到这个符合范围的数字还得额外折腾,用@直接就把匹配到的值绑定给n,分支里直接用就行。精准捕获子模式的值:当子模式是复杂结构(比如元组、结构体)时,@能帮你把整个符合子模式的部分绑定下来,而不是只拿到结构里的某一块。比如匹配元组的场景:
let pair = (2, 3); match pair { (a @ 1..=5, b) => println!("First element is in range: {}, second is {}", a, b), _ => println!("Not matching"), }这里
a @ 1..=5既验证了元组第一个元素在1-5之间,又把这个元素的值绑定给a,分支里直接就能用,不用再从原pair里重新取值。让代码更易懂:有时候外部变量的名字可能和当前分支的场景不搭,用@绑定一个贴合场景的变量名,能让代码逻辑一目了然。比如上面枚举例子里的
n,比临时去解构取值要直观多了。
说白了,这个语法就是给你提供了一种“既做模式匹配,又存下匹配值备用”的便捷方式,简单场景下可能看不出优势,但碰到复杂的匹配逻辑时,你绝对会觉得它香!
内容来源于stack exchange
相关产品推荐
相关产品推荐

