Rust 1.7.0 匹配器 match 的简单介绍和使用

释放双眼,带上耳机,听听看~!

使用过正则表达式的人应该都知道 matcher ,通过 matcher 匹配器运算正则表达式,完成一系列的匹配规则。

在Rust 中 没有 switch 语句,matcher 就是 switch 的一个变形,但比其他语言中的 switch 更强大!

一、简单举例说明

简单的 matcher 和 if 语句非常类似,如果是简单的条件判断可以用if语句:


1
2
3
4
5
6
7
8
9
10
11
1let n = 5;
2
3if n < 0 {
4    print!("{} is negative", n);
5} else if n > 0 {
6    print!("{} is positive", n);
7} else {
8    print!("{} is zero", n);
9}
10
11

复杂一些的条件判断,使用 if 语句就有些力不从心了。 match 可以这样:


1
2
3
4
5
6
7
8
9
10
11
1let x = 5;
2
3match x {
4    1 => println!("one"),
5    2 => println!("two"),
6    3 => println!("three"),
7    4 => println!("four"),
8    5 => println!("five"),
9    _ => println!("something else"),
10}
11

如果 x == 1 ,打印 one
如果 x == 2, 打印 two
如果 x == 3, 打印 three
如果 x == 4, 打印 four
如果 x == 5, 打印 five
如果没有与 x 匹配的值,
则执行 _ 对应的语句,打印 something else。

解释一下上面的代码的match语句,

  • match 是关键字;
  • x 是表达式;(非结构化的文本表达式)
  • match语句内容包含在 {}大括号中;
  • 括号中的每个 => 叫做 match-arm;
  • 大括号中可以包括任意多个 match-arm;
  • 当 x 存在可能不匹配的情况时,大括号中必须包含 _ => 来覆盖任何不匹配的情况下执行的语句,就像 switch 中的 default 一样。

match语句中 x 表达式的值,要与{}大括号中的每个match-arm分支进行匹配。如果匹配,则执行匹配 match-arm 中 =>后面的语句。

match本身也是个表达式,Rust就是基于表达式的语言。表达式是可以作为右值使用的。

所谓右值,就是看一个表达式能否放到等号的=等号右边,
比如x = 1+2,1+2可以发到=的右边,所以 1+2可以是个右值;
但是 1+2 = x,这个语句中1+2不能放到=等号的左边,所以 1+2不可能是左值。


1
2
3
4
5
6
7
8
9
10
11
1let x = 5;
2
3let number = match x {
4    1 => "one",
5    2 => "two",
6    3 => "three",
7    4 => "four",
8    5 => "five",
9    _ => "something else",
10};
11

这个 match 语句完成了 数字 变 字符 的转换,number中的值是 five 。

二、另外几个例子

单值、多值和范围匹配


1
2
3
4
5
6
7
8
9
10
1let number = 13;  
2println!("Tell me about {}", number);
3match number {
4    1 => println!("One!"),
5    2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
6    13...19 => println!("A teen"),
7    _ => println!("Ain't special"),
8}
9
10

布尔值的例子


1
2
3
4
5
6
7
8
1  let boolean = true;
2  let binary = match boolean {
3   false => 0,
4    true => 1,
5  };  
6  println!("{} -> {}", boolean, binary);
7
8

这里不存在 _ =>这个 match-arm,是因为 true 和 false这两个值已经完全覆盖boolean的所有值域。

枚举的例子


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1enum Message {
2    Quit,
3    ChangeColor(i32, i32, i32),
4    Move { x: i32, y: i32 },
5    Write(String),
6}
7
8fn quit() { /* ... */ }
9fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
10fn move_cursor(x: i32, y: i32) { /* ... */ }
11
12fn process_message(msg: Message) {
13    match msg {
14        Message::Quit => quit(),
15        Message::ChangeColor(r, g, b) => change_color(r, g, b),
16        Message::Move { x: x, y: y } => move_cursor(x, y),
17        Message::Write(s) => println!("{}", s),
18    };
19
20

这里的 match msg 也没有实现 _ => 这个match-arm,是因为match msg 里面的值完全覆盖了枚举 Message 中的值,如果把match msg 中的任意一个 match-arm 去掉,就必须实现 _ => 语句了。


1
2
3
4
5
6
7
1match msg {
2        Message::ChangeColor(r, g, b) => change_color(r, g, b),
3        Message::Move { x: x, y: y } => move_cursor(x, y),
4        Message::Write(s) => println!("{}", s),
5        _=> quit(),
6    };
7

条件选择


1
2
3
4
5
6
7
8
1let n  = 3;
2match n  {
3  n if n > 2 => println!("> 2"),
4  n if n < 3 => println!("< 3"),
5  _ => println!("some else"),
6};
7
8

在 match-arm的 => 前面可以有一个if 条件,即使 match 匹配,还可以通过 if 进行过滤。

如果这样,又如何呢?


1
2
3
4
5
6
7
8
1let n  = 4;
2match n  {
3  n if n > 2 => println!("> 2"),
4  n if n > 3 => println!("> 3"),
5  _ => println!("some else"),
6};
7
8

match 遇到第一个匹配的结果,就不再往下继续匹配了,只执行第一个满足条件的语句。

上面的代码变体:


1
2
3
4
5
6
1let n  = 4;
2match n  {
3  x => println!(" x = {}",x),
4};
5
6

x 被赋值 n ,即:let x = n。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

安全技术

阿里云Linix上 python脚本 发邮件发送不出去问题

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索