|
|
@ -23,7 +23,7 @@ fn main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这里我们想去匹配`dire`对应的枚举类型,因此在match中用三个匹配分支来完全覆盖枚举变量`Direction`的所有成员类型,有以下几点值得注意:
|
|
|
|
这里我们想去匹配 `dire` 对应的枚举类型,因此在 `match` 中用三个匹配分支来完全覆盖枚举变量 `Direction` 的所有成员类型,有以下几点值得注意:
|
|
|
|
- `match` 的匹配必须要穷举出所有可能,因此这里用 `_` 来代表未列出的所有可能性
|
|
|
|
- `match` 的匹配必须要穷举出所有可能,因此这里用 `_` 来代表未列出的所有可能性
|
|
|
|
- `match` 的每一个分支都必须是一个表达式,且所有分支的表达式最终返回值的类型必须相同
|
|
|
|
- `match` 的每一个分支都必须是一个表达式,且所有分支的表达式最终返回值的类型必须相同
|
|
|
|
- **X | Y**,是逻辑运算符 `或`,代表该分支可以匹配 `X` 也可以匹配 `Y`,只要满足一个即可
|
|
|
|
- **X | Y**,是逻辑运算符 `或`,代表该分支可以匹配 `X` 也可以匹配 `Y`,只要满足一个即可
|
|
|
@ -71,13 +71,13 @@ fn value_in_cents(coin: Coin) -> u8 {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`value_in_cents`函数根据匹配到的硬币,返回对应的美分数值,`match`后紧跟着的是一个表达式,跟`if`很像,但是`if`后的表达式必须是一个布尔值,而`match`后的表达式返回值可以是任意类型,只要能跟后面的分支中的模式匹配起来即可,这里的`coin`是枚举`Coin`类型。
|
|
|
|
`value_in_cents` 函数根据匹配到的硬币,返回对应的美分数值。`match` 后紧跟着的是一个表达式,跟 `if` 很像,但是 `if` 后的表达式必须是一个布尔值,而 `match` 后的表达式返回值可以是任意类型,只要能跟后面的分支中的模式匹配起来即可,这里的 `coin` 是枚举 `Coin` 类型。
|
|
|
|
|
|
|
|
|
|
|
|
接下来是 `match` 的分支。一个分支有两个部分:**一个模式和针对该模式的处理代码**。第一个分支的模式是 `Coin::Penny`,其后的 `=>` 运算符将模式和将要运行的代码分开。这里的代码就仅仅是表达式 `1`,不同分支之间使用逗号分隔。
|
|
|
|
接下来是 `match` 的分支。一个分支有两个部分:**一个模式和针对该模式的处理代码**。第一个分支的模式是 `Coin::Penny`,其后的 `=>` 运算符将模式和将要运行的代码分开。这里的代码就仅仅是表达式 `1`,不同分支之间使用逗号分隔。
|
|
|
|
|
|
|
|
|
|
|
|
当 `match` 表达式执行时,它将目标值 `coin` 按顺序依次与每一个分支的模式相比较,如果模式匹配了这个值,那么模式之后的代码将被执行。如果模式并不匹配这个值,将继续执行下一个分支。
|
|
|
|
当 `match` 表达式执行时,它将目标值 `coin` 按顺序依次与每一个分支的模式相比较,如果模式匹配了这个值,那么模式之后的代码将被执行。如果模式并不匹配这个值,将继续执行下一个分支。
|
|
|
|
|
|
|
|
|
|
|
|
每个分支相关联的代码是一个表达式,而表达式的结果值将作为整个 match 表达式的返回值。如果分支有多行代码,那么需要用`{}`包裹,同时最后一行代码需要是一个表达式。
|
|
|
|
每个分支相关联的代码是一个表达式,而表达式的结果值将作为整个 `match` 表达式的返回值。如果分支有多行代码,那么需要用 `{}` 包裹,同时最后一行代码需要是一个表达式。
|
|
|
|
|
|
|
|
|
|
|
|
#### 使用 `match` 表达式赋值
|
|
|
|
#### 使用 `match` 表达式赋值
|
|
|
|
还有一点很重要,`match` 本身也是一个表达式,因此可以用它来赋值:
|
|
|
|
还有一点很重要,`match` 本身也是一个表达式,因此可以用它来赋值:
|
|
|
@ -98,7 +98,7 @@ fn main() {
|
|
|
|
println!("{}", ip_str);
|
|
|
|
println!("{}", ip_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
因为这里匹配到`_`分支,所以将`"::1"`赋值给了`ip_str`.
|
|
|
|
因为这里匹配到 `_` 分支,所以将 `"::1"` 赋值给了 `ip_str`。
|
|
|
|
|
|
|
|
|
|
|
|
#### 模式绑定
|
|
|
|
#### 模式绑定
|
|
|
|
|
|
|
|
|
|
|
@ -223,7 +223,7 @@ error[E0004]: non-exhaustive patterns: `West` not covered // 非穷尽匹配,`
|
|
|
|
= note: the matched value is of type `Direction`
|
|
|
|
= note: the matched value is of type `Direction`
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
不禁想感叹,`Rust`的编译器真**强大,忍不住爆粗口了,sorry,如果你以后进一步深入使用Rust也会像我这样感叹的。Rust编译器清晰地知道`match`中有哪些分支没有被覆盖, 这种行为能强制我们处理所有的可能性,有效避免传说中价值十亿美金的`null`陷阱。
|
|
|
|
不禁想感叹,Rust 的编译器**真强大**,忍不住爆粗口了,sorry,如果你以后进一步深入使用 Rust 也会像我这样感叹的。Rust 编译器清晰地知道 `match` 中有哪些分支没有被覆盖, 这种行为能强制我们处理所有的可能性,有效避免传说中价值**十亿美金**的 `null` 陷阱。
|
|
|
|
|
|
|
|
|
|
|
|
#### `_` 通配符
|
|
|
|
#### `_` 通配符
|
|
|
|
|
|
|
|
|
|
|
@ -263,10 +263,10 @@ if let Some(3) = some_u8_value {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
这两种匹配对于新手来说,可能有些难以抉择,但是只要记住一点就好:**当你只要匹配一个条件,且忽略其他条件时就用`if let`,否则都用match**。
|
|
|
|
这两种匹配对于新手来说,可能有些难以抉择,但是只要记住一点就好:**当你只要匹配一个条件,且忽略其他条件时就用 `if let` ,否则都用 `match`**。
|
|
|
|
|
|
|
|
|
|
|
|
## matches!宏
|
|
|
|
## matches!宏
|
|
|
|
Rust标准库中提供了一个非常实用的宏:`matches!`,它可以将一个表达式跟模式进行匹配,然后返回匹配的结果`true` or `false`。
|
|
|
|
Rust 标准库中提供了一个非常实用的宏:`matches!`,它可以将一个表达式跟模式进行匹配,然后返回匹配的结果 `true` or `false`。
|
|
|
|
|
|
|
|
|
|
|
|
例如,有一个动态数组,里面存有以下枚举:
|
|
|
|
例如,有一个动态数组,里面存有以下枚举:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
@ -285,7 +285,7 @@ fn main() {
|
|
|
|
v.iter().filter(|x| x == MyEnum::Foo);
|
|
|
|
v.iter().filter(|x| x == MyEnum::Foo);
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
但是,实际上这行代码会报错,因为你无法将`x`直接跟一个枚举成员进行比较。好在,你可以使用`match`来完成,但是会导致代码更为啰嗦,是否有更简洁的方式?答案是使用`matches!`:
|
|
|
|
但是,实际上这行代码会报错,因为你无法将 `x` 直接跟一个枚举成员进行比较。好在,你可以使用 `match` 来完成,但是会导致代码更为啰嗦,是否有更简洁的方式?答案是使用 `matches!`:
|
|
|
|
```rust
|
|
|
|
```rust
|
|
|
|
v.iter().filter(|x| matches!(x, MyEnum::Foo));
|
|
|
|
v.iter().filter(|x| matches!(x, MyEnum::Foo));
|
|
|
|
```
|
|
|
|
```
|
|
|
|