可以使用所有 Places 模式
Patterns 在 Rust 中的许多地方都出现了,你已经经常使用它们了 不知不觉中!本节讨论模式所在的所有位置 有效。
match
武器
如第 6 章所述,我们在match
表达 式。
正式match
表达式定义为关键字match
,将值设置为
match on,以及一个或多个由 pattern 和
表达式,如果值与该 Arm 的模式匹配,则运行,如下所示:
match VALUE {
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
PATTERN => EXPRESSION,
}
例如,下面是match
表达式,它与Option<i32>
value 在变量中x
:
match x {
None => None,
Some(i) => Some(i + 1),
}
此match
expression 是None
和Some(i)
在
每个箭头的左侧。
一个要求match
expressions 的 API 表达式中,它们需要在
感觉match
表达式必须
被考虑。确保您已涵盖所有可能性的一种方法是拥有
最后一个分支的 catchAll 模式:例如,与任何
value 永远不会失败,因此涵盖了所有剩余的情况。
特定模式将匹配任何内容,但它永远不会绑定到
variable,因此它经常用于 last match 臂。模式可以是
例如,当您想要忽略任何未指定的值时很有用。我们将
在“忽略 a 中的值”中更详细地介绍了该模式
Pattern“ 部分
章。_
_
_
有條件的if let
表达 式
在第 6 章中,我们讨论了如何使用if let
表达主要作为较短的
编写match
这只匹配一个 case。
选择if let
可以具有相应的else
包含要运行的代码
的if let
不匹配。
示例 18-1 表明也可以混合和匹配if let
,else if
和else if let
表达 式。这样做比match
表达式中,我们只能表示一个值来与
模式。此外,Rust 并不要求一系列if let
,else if
,else if let
手臂彼此相关。
示例 18-1 中的代码决定了背景的颜色 针对多个条件的一系列检查。在此示例中,我们创建了 具有实际程序可能从用户那里接收的硬编码值的变量 输入。
文件名: src/main.rs
fn main() { let favorite_color: Option<&str> = None; let is_tuesday = false; let age: Result<u8, _> = "34".parse(); if let Some(color) = favorite_color { println!("Using your favorite color, {color}, as the background"); } else if is_tuesday { println!("Tuesday is green day!"); } else if let Ok(age) = age { if age > 30 { println!("Using purple as the background color"); } else { println!("Using orange as the background color"); } } else { println!("Using blue as the background color"); } }
示例 18-1:混合if let
,else if
,else if let
,
和else
如果用户指定了最喜欢的颜色,则该颜色将用作背景。 如果未指定收藏夹颜色,并且今天是星期二,则背景色为 绿。否则,如果用户将他们的年龄指定为字符串,并且我们可以解析 它成功作为一个数字,颜色是紫色或橙色,具体取决于 数字的值。如果这些条件都不适用,则背景 颜色是蓝色。
这种条件结构使我们能够支持复杂的需求。使用
hardcoded values 的 hardcoded 值,此示例将打印Using purple as the background color
.
你可以看到if let
也可以以相同的方式引入隐藏变量
那match
武器罐:LINEif let Ok(age) = age
引入了一个新的
阴影age
变量,其中包含Ok
变体。这
意味着我们需要将if age > 30
condition 的 SET 中:我们不能
将这两个条件合并为if let Ok(age) = age && age > 30
.这
阴影age
We Want to compare to 30 在新范围开始之前无效
带大括号。
使用if let
expressions 是编译器不检查
for exhaustiveness,而使用match
表达式。如果我们省略了
最后else
块,因此错过了处理某些情况,编译器将
不会提醒我们可能的 logic 错误。
while let
条件循环
在结构上类似于if let
这while let
条件循环允许while
循环运行。在列表中
18-2 我们编写一个while let
循环,该循环使用向量作为堆栈并打印
值,其推送顺序与它们被推送的顺序相反。
fn main() { let mut stack = Vec::new(); stack.push(1); stack.push(2); stack.push(3); while let Some(top) = stack.pop() { println!("{top}"); } }
示例 18-2:使用while let
循环打印值
只要stack.pop()
返回Some
此示例打印 3、2 和 1。这pop
method 采用最后一个元素
out 并返回Some(value)
.如果 vector 为空,则pop
返回None
.这while
循环继续运行其块中的代码,因为
只要pop
返回Some
.什么时候pop
返回None
,则循环停止。我们可以
用while let
将每个元素从堆栈中弹出。
for
循环
在for
loop 的值,该值紧跟在关键字for
是一个
模式。例如,在for x in y
这x
是模式。示例 18-3
演示如何在for
loop 进行解构,或 break
apart,一个元组作为for
圈。
fn main() { let v = vec!['a', 'b', 'c']; for (index, value) in v.iter().enumerate() { println!("{value} is at index {index}"); } }
示例 18-3:在for
loop 设置为
解构元组
示例 18-3 中的代码将打印以下内容:
$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
Running `target/debug/patterns`
a is at index 0
b is at index 1
c is at index 2
我们使用enumerate
方法,因此它会生成一个值,而
该值的索引,放置在 Tuples 中。生成的第一个值是
元(0, 'a')
.当此值与模式匹配时(index, value)
,index
将是0
和value
将是'a'
,打印
输出。
let
语句
在本章之前,我们只明确讨论了使用match
和if let
,但实际上,我们在其他地方也使用了 pattern,
包括let
语句。例如,考虑一下这个简单的
变量赋值let
:
#![allow(unused)] fn main() { let x = 5; }
每次您使用let
语句,就像这样,你一直在使用 patterns,
尽管您可能没有意识到!更正式地说,一个let
声明外观
喜欢这个:
let PATTERN = EXPRESSION;
在像let x = 5;
的PATTERN
slot 中,
变量名称只是模式的一种特别简单的形式。Rust 比较
表达式,并为其找到的任何名称分配。因此,在let x = 5;
例x
是一种模式,表示“将此处匹配的内容绑定到
变量x
.”因为x
是整个模式,这个模式
实际上意味着 “将所有内容绑定到变量x
,无论价值是多少。
要查看 的模式匹配方面let
更明确地说,考虑列出
18-4 中,它使用带有let
来解构一个元组。
fn main() { let (x, y, z) = (1, 2, 3); }
示例 18-4:使用模式解构元组和 一次创建三个变量
在这里,我们将元组与模式进行匹配。Rust 比较了(1, 2, 3)
到模式(x, y, z)
并看到该值与模式匹配,因此 Rust
绑定1
自x
,2
自y
和3
自z
.你可以考虑这个元组
pattern 嵌套三个单独的可变 pattern。
如果模式中的元素数与元素数不匹配 在 Tuples 中,整体类型不匹配,我们将收到 Compiler 错误。为 例如,示例 18-5 展示了一个尝试用 3 个 元素转换为两个变量,这不起作用。
fn main() {
let (x, y) = (1, 2, 3);
}
示例 18-5:错误地构造一个 变量与元组中的元素数不匹配
尝试编译此代码会导致以下类型错误:
$ cargo run
Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0308]: mismatched types
--> src/main.rs:2:9
|
2 | let (x, y) = (1, 2, 3);
| ^^^^^^ --------- this expression has type `({integer}, {integer}, {integer})`
| |
| expected a tuple with 3 elements, found one with 2 elements
|
= note: expected tuple `({integer}, {integer}, {integer})`
found tuple `(_, _)`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `patterns` (bin "patterns") due to 1 previous error
要修复此错误,我们可以使用 或_
..
,如您在
Pattern“部分。如果问题
是我们在 pattern 中有太多的变量,解决方案是让
类型通过删除变量进行匹配,使变量的数量等于数字
元组中的元素。
功能参数
函数参数也可以是模式。示例 18-6 中的代码,其中
声明一个名为foo
它接受一个名为x
的类型i32
现在应该看起来很熟悉。
fn foo(x: i32) { // code goes here } fn main() {}
示例 18-6:函数签名使用 参数
这x
部分是图案!正如我们对let
中,我们可以匹配
函数的参数传递给模式。示例 18-7 将值拆分为一个 Tuples
当我们将其传递给函数时。
文件名: src/main.rs
fn print_coordinates(&(x, y): &(i32, i32)) { println!("Current location: ({x}, {y})"); } fn main() { let point = (3, 5); print_coordinates(&point); }
示例 18-7:一个带有解构参数的函数 一个元组
此代码打印Current location: (3, 5)
.值&(3, 5)
匹配
模式&(x, y)
所以x
是值3
和y
是值5
.
我们也可以像 function parameter lists 的 API API 中,因为闭包类似于函数,因为 在第 13 章中讨论。
此时,您已经看到了几种使用 patterns 的方法,但 patterns 没有 在我们可以使用它们的每个地方都以相同的方式工作。在某些地方,模式必须 无可辩驳;在其他情况下,它们可以被反驳。我们将讨论 接下来是这两个概念。
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准