首页 > 其他分享 >Rust从入门到精通09-模式解构

Rust从入门到精通09-模式解构

时间:2022-10-05 14:00:31浏览次数:58  
标签:Direction fn West 09 解构 let Rust println match

"Pattern Destructure" 是 Rust 中一个重要且实用的设计。通常翻译为 “模式解构”。

Destructure 单词翻译为把原来的结构肢解为单独的、原始的部分。

下面我们举例说明什么是模式解构:

fn main() {
let tul = (1,"a",false);
let (head,center,tail) = tul;
println!("{}",head);//1
println!("{}",center);//a
println!("{}",tail);//false
}

第2行代码是构造;第3行代码是拆解,产生了三个新的变量。

Rust 的模式解构不仅出现在 let 语句中,还可以出现在 match、if let、while let、函数调用、闭包调用等情景中。

1、match

1.1 用于匹配多种取值
rustenum Direction{
East,
West,
South,
North,
}
fn print(x:Direction){
match x {
Direction::East => {
println!("East");
}
Direction::West => {
println!("West");
}
Direction::South => {
println!("South");
}
Direction::North => {
println!("North");
}
}
}

当一个类型有多种取值时,特别适合适用 match 表达式。可以等价于 if-else

1.2 必须匹配到每个分支exhaustive

exhuastive:彻底的,详尽的

对应到 match 表达式上,Rust 要求 match 需要对所有的情况做彻底的,无遗漏的匹配。比如对于上面的例子,我们删除一个匹配分支(East)

注意:编译器会保证 match 所有分支合起来一定覆盖了所有的情况,但是不保证各个分支重复的问题。

enum Direction{
East,
West,
South,
North,
}
fn print(x:Direction){
match x {
Direction::West => {
println!("West");
}
Direction::South => {
println!("South");
}
Direction::North => {
println!("North");
}
}
}
fn main() {
print(Direction::West);
}

编译就会报错:

Rust从入门到精通09-模式解构_取值

1.3 一个分支匹配多种类型 |

我们可以通过 | 在一个分支匹配多种情况;

enum Direction{
East,
West,
South,
North,
}
fn print(x:Direction){
match x {
Direction::East => {
println!("East");
}
Direction::West | Direction::South | Direction::North=> {
println!("Other");
}
}
}
1.3 通配模式和 _ 占位符

有时候,我们并不知道到底有多少种匹配情况,这时候可能需要一个类似通配符,来匹配所有没有考虑的情况,从而避免编译失败。

fn print(x:Direction){
match x {
Direction::West => {
println!("West");
}
Direction::South => {
println!("South");
}
other => {
println!("orther");
}

}
}

上面代码前面两个分支我们匹配了 West 和 South,剩下两个分支我们直接定义了一个名为 other 的变量(这个变量可以任意命名),它将匹配所有未被特殊列出来的值。

需要注意:我们必须将通配分支放在最后,因为模式是按顺序匹配的。如果我们在通配分支后添加其他分支,Rust 将会警告我们,因为此后的分支永远不会被匹配到。

除此之外,Rust 还推出了"_" 占位符来匹配所有情况。

enum Direction{
East,
West,
South,
North,
}
fn print(x:Direction){
match x {
Direction::East => {
println!("East");
}
_ => {
println!("other");
}
}
}
1.4 忽略匹配占位符 _

下划线除了用作 match 表达式中的分支额外匹配之外,还可以用来表示一个占位符,表示虽然匹配到了,但是忽略掉。

struct P(i32,i32,i32);
fn add(p:P) -> i32{
let P(x,_,y) = p;
x+y
}
fn main() {
let p = P(1,2,3);
println!("{}",add(p));//4
}

我们只想求元祖结构体P的第一个和末尾数据之和,所以中间的数据可以通过_ 忽略掉。

1.5 match guards 匹配看守

match 和 if 配合一起使用。

enum OptionalInt{
Value(i32),
Missing,
}
fn match_if(op:OptionalInt){
match op {
OptionalInt::Value(i) if i > 10 => {println!("big int")}
OptionalInt::Missing => println!("not int")
}
}

但是上面这段代码会编译错误,提示没有覆盖所有的情况。(如果移除 if 条件,是正常编译的)

Rust从入门到精通09-模式解构_下划线_02

那么如何修改这个问题呢?我们增加 if 匹配条件看看:

fn match_if(op:OptionalInt){
match op {
OptionalInt::Value(i) if i > 10 => {println!("big int")},
OptionalInt::Value(i) if i<= 10 => {println!("get int")},
OptionalInt::Missing => println!("not int"),
}
}

发现还是编译失败

我们已经通过 if 覆盖了所有的情况,但是还是不能编译通过,这其实也是 rust 编译器目前无法做到的,它毕竟不是一个完整的数学解析器。

这种情况下,我们加个下划线匹配就可以了。

fn match_if(op:OptionalInt){
match op {
OptionalInt::Value(i) if i > 10 => {println!("big int")},
OptionalInt::Value(i) if i<= 10 => {println!("get int")},
_ => println!("没有特殊意义"),
OptionalInt::Missing => println!("not int"),
}
}

2、if-let

比如有一个类型为 Option 的变量 val,我们要取出里面的值。

①、使用match表达式

fn getOptionVal(str:Option<String>) -> String{
match str {
Some(x) => x,
None => panic!("called `Option::unwrap()` on a `None` value")
}

}
fn main() {
let val = Some("ab".into());
println!("{}",getOptionVal(val));//ab
}

②、if 表达式

fn getOptionVal(str:Option<String>) -> String{
if str.is_some(){
return str.unwrap();
}
panic!("called `Option::unwrap()` on a `None` value")
}
fn main() {
let val = Some("ab".into());

println!("{}",getOptionVal(val));//ab
}

③、if-let

fn getOptionVal(str:Option<String>) -> String{
if let Some(x) = str{
return x;
}
panic!("called `Option::unwrap()` on a `None` value")
}
fn main() {
let val = Some("ab".into());
println!("{}",getOptionVal(val));//ab
}

第二种方法(if 表达式)取值分两步,第一步调用 is_some()判断,第二步调用unwrap()取值;

而if-let 看上去就简洁很多,但是和 if 表达式相比并没有效率上的差别,只是rust提供的一个语法糖。

标签:Direction,fn,West,09,解构,let,Rust,println,match
From: https://blog.51cto.com/u_12749768/5732637

相关文章

  • 09_使用SDL播放PCM
    通过命令ffpay播放PCM可以使用ffplay播放《08_音频录制02_编程》中录制好的PCM文件,测试一下是否录制成功。播放PCM需要指定相关参数:ar:采样率ac:声道数f:采样格式,sam......
  • Rust学习 - Sized trait
    Sizedtrait的作用是什么?编译期用它来识别在编译期确定大小的类型。Sizedtrait是空trait,仅仅作为标签trait供编译期使用。真正起“打标签”作用的是属性#[lang="s......
  • Rust 链式调用引发的问题 consider using a `let` binding to create a longer lived
        temporaryvaluedroppedwhileborrowedconsiderusinga`let`bindingtocreatealongerlivedvalue为什么会报这个错?因为maps.lock.unwrap.values.........
  • 09-RabbitMQ核心API-Fanout Exchange
    FanoutExchange简介不处理路由键,只需要简单的将队列绑定到交换机上发送到交换机的消息都会被转发到与该交换机绑定的所有队列上Fanout交换机转发消息是最快的......
  • 【Ynoi2009】 rla1rmdq 题解 (离线分块 + 线性空复处理)
    洛谷传送门分块。Solution看到是区修区查,还有时限,不难想到是分块,根号复杂度。然后看到空间复杂度,需要离线下来转为线性复杂度。考虑如何分块。观察操作性质,发现节点......
  • CSP202209_3
    CSP202209_3目录CSP202209_3题目思路Code题目防疫大数据思路大模拟。大致题意就是针对当前天,给出以当天开始持续七天的风险地区。同时给出一定数量的用户信息,包括其......
  • 202209_2
    CSP202209_2目录CSP202209_2题目思路DFSDPCode题目何以包邮思路DFS直接DFS,对每件物品根据选与不选进行搜索。当前总价值已经大于答案或者已经满足条件了就显然没有搜......
  • Rust从入门到精通08-字符串
    Rust字符串相对于其它语言有点复杂,主要是跟所有权有关。Rust字符串涉及两种类型:&str和String1、&str-字面量str是Rust的内置类型,&str是str的借用。可以理解为字符......
  • 正经人谁记日记 2022-09-25 周日 21:51:39
    做时间的主人书是人类进步的阶梯作者:DATA_MONK​,转载请注明原文链接​......
  • 2022-09-26 周一
    作者:DATA_MONK​,转载请注明原文链接​......