文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
3.3 匹配
类似 switch
,将值与多个模式比较,依匹配结果执行分支代码。模式可以是变量、字面量、通配符,或其他内容。
match VALUE { PATTERN => EXPRESSION, ... }
限制:
- 模式必须覆盖(cover)所有值。
- 分支代码是表达式,其结果作为返回值。
- 分支代码块(block)以逗号结束。
- 以
_
实现默认(default)分支。
重复模式会输出警告信息 unreachable pattern,不会出错。默认分支必须放在最后,否则也会导致 unreachable pattern。
fn main() { let x = 3; match x { 1 => println!("1"), 2 => println!("2"), 3 | 4 => println!("3 | 4"), // or _ => {}, // 放在最后! } }
let x = 1; match x { 1 ..= 5 => println!("1 ... 5"), // range _ => println!("..."), }
可用于赋值。
let x = 5; let number = match x { 1 => "one", 2 => "two", 3 => "three", 4 => "four", 5 => "five", _ => "something else", };
模式
相比其他语言的 switch 语句,match 和 pattern 结合,可优雅完成解构操作。
考虑到 value 可能是个表达式,所以分支定义一个接收值的局部变量很有必要。
fn main() { let x = 1; let c = ||{ 'c' }; // 匿名函数。 match c() { x => println!("{}, {:p}", x, &x), // let x = c() } // 匹配所有值。 println!("{}, {:p}", x, &x) // 地址不同! } // c, 0x7fff50a16e7c // 1, 0x7fff50a16e78
解构复合类型。
枚举成员可附加额外数据,诸如单值、元组或结构。
enum X { A(i32, String), B{x: i32, y: i32}, } fn main() { let x = X::B{ x: 11, y: 22 }; match x { X::A(a, b) => println!("{} {}", a, b), X::B{x, y} => println!("{} {}", x, y), // 或 X::B{x:a, y:b} => a, b } }
fn main() { let d = (1, 2, 3, 4); match d { (x, .., y) => println!("{}..{}", x, y), // 解构元组局部元素。 // (x, ..) => println!("{}", x), // (.., y) => println!("{}", y), } } // 1..4
struct Point { x: i32, y: i32, } let origin = Point { x: 1, y: 2 }; match origin { Point{x, y} => println!("{},{}", x, y), // 或 Point{x:a, y:b} => a, b } // 部分忽略:Point{x, ..} => // 匹配类型:Point{..} => // 单个忽略:_
匹配类型要写成
T{..}
,光有类型名会被当作局部变量。
增加匹配条件,诸如部分值、范围、选择条件等。
fn main() { let d = [1, 2, 3, 4, 5, 6]; match d { [0, 1, 2, ..] => println!("a"), [.., 6, 7] => println!("b"), [1, .., 6] => println!("c"), _ => println!("n"), } } // c
fn main() { struct Foo { x: (u32, u32), y: u32, } let foo = Foo { x: (1, 2), y: 3 }; match foo { Foo{ x: (1, b), y } => println!("{}, {} ", b, y), // 含部分值的深层解构。 Foo{ y: 2, x: i } => println!("{}", i.0), Foo{ y, .. } => println!("{}", y), } } // 2, 3
fn main() { let x = 4; match x { n @ 1 ..= 5 => println!("a: {}", n), n => println!("b: {}", n), // 其他(可用 _ 忽略) } } // a: 4
fn main() { let x = 5; match x { 1 ..= 10 if x % 2 == 0 => println!("a"), n if n > 10 => println!("b"), _ => println!("c"), } } // c
获取引用与匹配引用的区别。
fn main() { let v = 100; match v { ref r => println!("{}", *r), // r: &i32 获取引用! } // 代替所有权转移或复制。 // 可变引用: ref mut r let r = &v; match r { &v => println!("{}", v), // v: i32 匹配引用,取值! } // 要求 value/r 必须是引用。 }
简单匹配
如果只关心单个模式,可用 if-let
或 while-let
代替,更简洁。
if let PATTERN = EXPRESSION { /* body */ } else { /*else */ }
match EXPRESSION { PATTERN => { /* body */ }, _ => { /* else */ }, // () if there is no else }
相比直接用 if
,多了模式解构操作。
struct Point { x: i32, y: i32, } fn main() { let p = Point {x: 1, y: 2}; match p { Point{x, y: 2} => println!("{}", x), _ => {}, } if let Point{x: n, y: 2} = p { // 判断类型和 y 值,解构。 println!("{}", n); } }
fn main() { let mut x = vec![1, 2, 3]; while let Some(n) = x.pop() { println!("{:?}", n); } }
注意解构临时变量作用域。
fn main() { let p = Point {x: 1, y: 2}; if let Point{x: n, y: 100} = p { println!("T: {}", n); } else { println!("F: {}", n); ^ cannot find value `n` in this scope } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论