可以使用所有 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),
}
此matchexpression 是None和Some(i)在
每个箭头的左侧。
一个要求matchexpressions 的 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 > 30condition 的 SET 中:我们不能
将这两个条件合并为if let Ok(age) = age && age > 30.这
阴影ageWe Want to compare to 30 在新范围开始之前无效
带大括号。
使用if letexpressions 是编译器不检查
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。这popmethod 采用最后一个元素
out 并返回Some(value).如果 vector 为空,则pop返回None.这while循环继续运行其块中的代码,因为
只要pop返回Some.什么时候pop返回None,则循环停止。我们可以
用while let将每个元素从堆栈中弹出。
for循环
在forloop 的值,该值紧跟在关键字for是一个
模式。例如,在for x in y这x是模式。示例 18-3
演示如何在forloop 进行解构,或 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:在forloop 设置为
解构元组
示例 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;的PATTERNslot 中,
变量名称只是模式的一种特别简单的形式。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/)为准