Match 是什么语法?PHP8 也加了

开发 前端
关于 match 表达式,很多其他语言并没有,比如 Go 语言。不过有些语言开始支持 match,比如 PHP 8.0 就有了 match 表达式。

[[404809]]

大家好,我是站长 polarisxu。

这是 Rust 劝退系列的第 8 个教程,探讨 Rust 中的模式匹配。

01 match 表达式

关于 match 表达式,很多其他语言并没有,比如 Go 语言。不过有些语言开始支持 match,比如 PHP 8.0 就有了 match 表达式。

一般地可以认为 match 和 switch 类似,所以 Rust 中没有 switch。

match 用于检查某个当前的值是否匹配一组/列值中的某一个。看一个具体的例子:

  1. fn test_match(number: i32) -> &'static str { 
  2.     match number { 
  3.         // 匹配单个值 
  4.         1 => {println!("One!"); "One!"}, 
  5.         // 匹配多个值 
  6.         2 | 3 | 5 | 7 | 11 => "This is a prime"
  7.         // 匹配一个闭区间范围 
  8.         13..=19 => "A teen"
  9.         // 处理其他情况 
  10.         _ => "Ain't special"
  11.     } 

看起来是一个简单的语法结构,但大概率在其他语言没见过。简单解释下:

  • 跟其他语言的 switch 类似,可以匹配多个分支;多个分支之间,使用 , 分隔;
  • 在 match 分支中,=> 左侧是模式,因此叫做模式匹配,比如 | 表示匹配多个值;..= 表示匹配一个范围;右侧是在左侧匹配成功时要执行的操作;
  • match 要求穷尽,也就是要包含所有可能的值。因此提供了 _,用来处理所有其他情况,类似 switch 的 default 分支;但只要穷尽了,可以没有 _;
  • 如果右侧操作是多个语句,需要放在 {} 中;
  • match 是表达式,它的结果是匹配到的模式中,执行操作的最后一个表达式的结果。这在 Rust 中是很常见的,之前提到过,Rust 中一切皆表达式。所以,这个例子中 match 表达式的值即为函数的返回值。因此,match 的所有分支必须返回同一数据类型;
  • 注意 match 表达式最后是否有分号的区别;

日常吐槽:在 match 中匹配区间,如果想和 for in 一样,使用 .. 来表示半闭半开区间,结果报错。看到资料说应该使用 …,但却提示该语法已废弃!为啥语法结构还不保持一致呢?!

看一个接收 match 结果的例子:

  1. let boolean = true
  2. let binary = match boolean { 
  3.   false => 0, 
  4.   true => 1, 
  5. }; // 注意这里的分号 
  6. println!("{} -> {}", boolean, binary); 

02 match 其他用法

上面介绍了常规的 match 操作。match 还有很多其他的用法。

解构

当元组和 match 一起时,可以解构元组。

  1. fn main() { 
  2.   // 试一试将不同的值赋给 `pair` 
  3.     let pair = (0, -2); 
  4.      
  5.     println!("Tell me about {:?}", pair); 
  6.     // match 可以解构一个元组 
  7.     match pair { 
  8.         // 解构出第二个值 
  9.         (0, y) => println!("First is `0` and `y` is `{:?}`", y), 
  10.         (x, 0) => println!("`x` is `{:?}` and last is `0`", x), 
  11.         _      => println!("It doesn't matter what they are"), 
  12.         // `_` 表示不将值绑定到变量 
  13.     } 

关于枚举和指针、引用和 match 的结合,以后遇到再讲解。

guard 语句

在 match 分支中可以加上过滤条件。接着上面元组解构的例子:

  1. fn main() { 
  2.     let pair = (2, -2); 
  3.  
  4.     println!("Tell me about {:?}", pair); 
  5.     match pair { 
  6.         (x, y) if x == y => println!("These are twins"), 
  7.         // `if` 条件部分是一个卫语句 
  8.         (x, y) if x + y == 0 => println!("Antimatter, kaboom!"), 
  9.         (x, _) if x % 2 == 1 => println!("The first one is odd"), 
  10.         _ => println!("No correlation..."), 
  11.     } 

绑定

这是什么意思呢?看一个例子:(来自 rust by example)

  1. // `age` 函数,返回一个 `u32` 值。 
  2. fn age() -> u32 { 
  3.     15 
  4.  
  5. fn main() { 
  6.     println!("Tell me type of person you are"); 
  7.  
  8.     match age() { 
  9.         0             => println!("I'm not born yet I guess"), 
  10.         // 可以直接 `match` 1 ..= 12,但怎么把岁数打印出来呢? 
  11.         // 在 1 ..= 12 分支中绑定匹配值到 `n` 。现在年龄就可以读取了。 
  12.         n @ 1  ..= 12 => println!("I'm a child of age {:?}", n), 
  13.         n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n), 
  14.         // 不符合上面的范围。返回结果。 
  15.         n             => println!("I'm an old person of age {:?}", n), 
  16.     } 

match 后是一个函数,我们希望在分支中,根据匹配结果,使用 age 函数的返回值。当然,这个例子有点多此一举,完全可以在 match 之前用变量存储 age 函数的返回值。

那换一个例子:

  1. fn some_number() -> Option<u32> { 
  2.     Some(41) 
  3.  
  4. fn main() { 
  5.     match some_number() { 
  6.         Some(n @ 40..=42) => println!("The Answer: {}!", n), 
  7.         Some(n)      => println!("Not interesting... {}", n), 
  8.         _            => (), 
  9.     } 
  • 关于 Option 以后讲解

这个例子很好的讲解了绑定的作用:分支中想要使用匹配的结果,通过 @ 符号可以将匹配的结果和某个变量绑定,然后就可以使用这个变量了。

03 if let 和 while let

这两个结构其他语言没见过,可以理解为是某些场景下替代 match,让代码更简洁,因为 match 必须穷尽所有情况,而 if let 和 while let 没有此限制。

以下代码:

  1. let some_u8_value = Some(3u8); 
  2. match some_u8_value { 
  3.   Some(3) => println!("three"), 
  4.   _ => (), // 有点多余 

改为 if let:

  1. let some_u8_value = Some(3u8); 
  2. if let Some(3) = some_u8_value { 
  3.  println!("three"); 

和 match 一样,if let 和 while let 都是表达式;

  • if/while let 等号左侧是模式,右侧是要匹配的值;所以当右侧的值和左侧的模式匹配时,执行对应的语句块;所以,有时候 if let 也可以单纯的当做解构使用;
  • if let 支持普通的 else if 和 else;while let 没有 else;
  • while let 语法和 if let 类似。这里就不举例子了。

04 小结

Rust 中的 match 虽然和其他语言的 switch 类似,很显然,match 的复杂度比 switch 高。当然,不管复杂与否,最关键还是要实际使用,需要不断实际练习。

 

通常,match 和 Option、枚举一起使用,因此,在讲解这两个知识点时,一般会使用到 match。

本文转载自微信公众号「polarisxu」,可以通过以下二维码关注。转载本文请联系polarisxu公众号。

 

责任编辑:武晓燕 来源: polarisxu
相关推荐

2020-07-19 07:44:16

PHP 8.0Match语法

2020-05-28 13:10:27

PHP开发编程

2021-01-12 08:57:55

Fedora 34PHP8开发

2022-08-28 10:47:22

Ubuntu

2012-03-16 21:25:14

Windows Pho

2021-01-14 12:14:13

PHPPHP 8WordPress

2023-02-26 23:36:08

PHPGo函数

2024-03-22 12:22:50

Vue前端

2011-06-27 08:35:28

2009-11-17 15:07:16

PHP数组遍历

2011-06-15 15:55:36

PHP

2024-04-02 08:02:11

Dockerk8s容器

2011-04-13 17:28:21

2023-01-11 09:56:41

索引SQL

2009-09-16 14:22:44

preg_match正

2009-12-10 15:58:21

PHP preg_ma

2009-11-30 17:02:13

PHP函数preg_m

2012-04-18 09:29:49

微软Windows 8RT

2009-05-13 14:15:09

PHP 5.3闭包匿名函数

2009-11-30 18:34:22

PHP简单语法
点赞
收藏

51CTO技术栈公众号