Rust控制流运算符match的用法详解
作者:qq5551230
概述
match 是Rust中一个极为强大的控制流运算符,用于模式匹配和控制流的选择。它允许将一个值与一系列的模式相比较,根据匹配的模式执行相应代码。模式可由字面量、变量、通配符和许多其他内容构成。
模式由以下元素(的一些组合)组成:
- 字面量
- 解构的数组
- 枚举类型
- 结构体
- 处理条件表达式
- 通配符
- 占位符
我们可以把match表达式想象成某种硬币分类器:硬币滑入有着不同大小孔洞的轨道,每个硬币都会掉入符合它大小的空洞。同样地,值也会通过match的每一个模式,并且在遇到第一个“符合”的模式时,值会进入相关的代码块并在执行中被使用。
基础语法
match value {
pattern1 => {
//code1
}
pattern2 => {
//code2
}
_ => {
//没有任何匹配
}
}基础语法中,value是要匹配的变量,pattern是匹配模式, => 后面是要执行的代码。末尾使用通配符“ - ”(下划线)表示其他情况。如果value匹配了某个模式,就执行相应代码块,如果value没有匹配任何模式,就会执行默认的代码块,即( _ => {...},)。
让我们编写一个函数来获取一个未知的硬币,并以一种类似验钞机的方式,确定它时何种硬币并返回它的美分值。
//一个枚举和一个以枚举成员作为模式的match表达式
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}如果分支代码较短的话通常不使用大括号,如果想要在分支中运行多行代码,可以使用大括号。
fn value_in_cents(coin:Coin) -> u8 {
match coin {
Coin::Penny => {
println!("Lucy penny!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter =>25,
}
}绑定值的模式
匹配分支的另一个有用的功能是可以绑定匹配的模式的部分值。也就是可以从枚举成员中提取值的方式。
举个例子,让我们修改枚举中的一个成员来存放数据。1999年到2008年间,美国在25美分的硬币的一侧为50个州的每一个都印刷了不同的设计。其他的硬币都没有这种区分州的设计,只有这些25美分的硬币有特殊的价值。可以将这些信息加入我们的enum,通过改变Quarter成员来包含一个State值。
//Quarter成员也存放一个UsState值的Coin枚举
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
//--snip--
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}假设我们的一个朋友正在尝试收集所有50个州25美分硬币。根据硬币类型分类零钱的同时,也可以报告出每个25美分硬币所对应的州名称,如果他没有的话,他可以将其加入收藏。
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime =>10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
}
}
}调用value_in_cents(Coin::Quarter(UsState::Alaska),coin将是Coin::Quarter(UsState::Alaska)。这时state绑定的值是UsState::Alaska。然后在pintln!表达式中使用这个绑定就可以获取Coin枚举的Quarter成员中内部的州的值。
匹配Option<T>
我们想要编写一个函数,它获取一个Option<i32>,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回None值,二不尝试执行任何操作。
// 一个Option<i32>上使用match表达式的函数
fn plus_one (x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i+1),
}
}
let five = Some(5);
let six =plus_one(five);
let none = plus_one(None);匹配Some(T)
匹配是穷尽的
Rust知道我们没有覆盖所有可能的情况甚至指导哪些模式被忘记了!Rust中的匹配时穷尽的:必须穷举到最后的可能性来使代码有效。特别是在Option<T>的例子中,Rust防止我们忘记明确的处理None的情况,这让我们免于假设拥有一个实际上为空的值,从而错误不可能发生。
通配符和 _ 占位符
假设我们正在玩一个游戏,如果你掷出骰子的值为3,角色不会移动,而是会得到一顶新奇的帽子。如果掷出骰子的值为7,你的角色将失去新奇的帽子。对于其他的数值,你的角色会在棋盘上移动相应的格子。
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
other => move_player(other),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}这是一个实现上述逻辑的match,匹配模式是字面值3和7,最后一个分支则涵盖了所有其他可能的值,模式是我们命名为other的一个变量。other分支的代码通过将其传递给move_player函数来使用这个变量。
最后一个模式没有列出u8所有可能的值,代码依旧能够编译。这种通配模式满足了match必须被穷尽的要求,必须将通配分支放在最后,因为模式是按顺序匹配的。
当我们不想使用通配模式获取的值时,可以使用 _ 模式。这个模式可以匹配任意值而不绑定到该值。
改变游戏规则:现在,当你掷出觉得值不是3或7的时候,你必须再次掷出。这种情况下我们不需要使用这个值。我们修改代码使用"_"代替变量other:
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
_ => reroll(),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn reroll() {}最后一个分支中明确忽略了其他的值,也满足了穷举性要求。
改变游戏规则:如果掷出3或7以外的值,你的回合将无事发生。使用单元值(空元组)作为_分支的代码:
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
_ => (),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}到此这篇关于Rust控制流运算符match的用法详解的文章就介绍到这了,更多相关Rust控制流运算符match内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
