当前位置: 首页 > news >正文

【Rust练习】16.模式

文章题目来自:https://practice-zh.course.rs/pattern-match/patterns.html

1 🌟🌟 使用 | 可以匹配多个值, 而使用 …= 可以匹配一个闭区间的数值序列


fn main() {}
fn match_number(n: i32) {match n {// 匹配一个单独的值1 => println!("One!"),// 使用 `|` 填空,不要使用 `..` 或 `..=`__ => println!("match 2 -> 5"),// 匹配一个闭区间的数值序列6..=10 => {println!("match 6 -> 10")},_ => {println!("match 11 -> +infinite")}}
}

将前面学到的模式匹配进行集合就可以了

fn match_number(n: i32) {match n {// 匹配一个单独的值1 => println!("One!"),// 使用 `|` 填空,不要使用 `..` 或 `..=`2 | 3 | 4 | 5 => println!("match 2 -> 5"),// 匹配一个闭区间的数值序列6..=10 => {println!("match 6 -> 10")}others => {println!("match 11 -> +infinite")}}
}

2 🌟🌟🌟 @ 操作符可以让我们将一个与模式相匹配的值绑定到新的变量上


struct Point {x: i32,y: i32,
}fn main() {// 填空,让 p 匹配第二个分支let p = Point { x: __, y: __ };match p {Point { x, y: 0 } => println!("On the x axis at {}", x),// 第二个分支Point { x: 0..=5, y: y@ (10 | 20 | 30) } => println!("On the y axis at {}", y),Point { x, y } => println!("On neither axis: ({}, {})", x, y),}
}

这里的语法可能会让有些人非常疑惑:明明xy就在这里,为什么我要再给y绑定一个变量?如果你直接编译上述代码(我指的是修改了p的赋值之后),你会遇到如下错误:
错误
y改成p.y就可以了。

我们先考虑另外一个场景:

fn age() -> u32 {15
}fn main() {println!("Tell me what type of person you are");match age() {0 => println!("I haven't celebrated my first birthday yet"),1..=12 => println!("I'm a child of age 1..12"),13..=19 => println!("I'm a teen of age 13..19"),_ => println!("I'm an old person of age others"),}
}

一个典型的根据年龄匹配打印的函数,那如果我希望将被匹配的值,也就是age()的返回值打印出来呢?这就不太好办了。也许可以在println!里再调用一次?你知道可以这么做只是因为这里age()返回的值是固定的,如果它每次返回的值都不一样,显然不能这么做。

这时,@绑定就派上用场了。

fn main() {println!("Tell me what type of person you are");match age() {0 => println!("I haven't celebrated my first birthday yet"),n @ 1..=12 => println!("I'm a child of age {:?}", n),n @ 13..=19 => println!("I'm a teen of age {:?}", n),n => println!("I'm an old person of age {:?}", n),}
}

我们将被匹配的值绑定到n上,后续代码逻辑就可以使用了。

再考虑上面的例子,归根结底,每次匹配都只是将外部的变量和范围进行匹配,中间没有产生任何额外的变量。所以如果你想使用,要么使用原始的外部变量,要么进行一个@绑定。而匹配所有值,本质上不是匹配,就是进行了一次绑定,所以绑定的值可以直接使用

3


// 修复错误
enum Message {Hello { id: i32 },
}fn main() {let msg = Message::Hello { id: 5 };match msg {Message::Hello {id:  3..=7,} => println!("id 值的范围在 [3, 7] 之间: {}", id),Message::Hello { id: newid@10 | 11 | 12 } => {println!("id 值的范围在 [10, 12] 之间: {}", newid)}Message::Hello { id } => println!("Found some other id: {}", id),}
}

第一个需要用@绑定,第二个需要全部匹配(落个括号)

// 修复错误
enum Message {Hello { id: i32 },
}fn main() {let msg = Message::Hello { id: 5 };match msg {Message::Hello {id:id@  3..=7,} => println!("id 值的范围在 [3, 7] 之间: {}", id),Message::Hello { id: newid@(10 | 11 | 12) } => {println!("id 值的范围在 [10, 12] 之间: {}", newid)}Message::Hello { id } => println!("Found some other id: {}", id),}
}

4 🌟🌟 匹配守卫(match guard)是一个位于 match 分支模式之后的额外 if 条件,它能为分支模式提供更进一步的匹配条件。


// 填空让代码工作,必须使用 `split`
fn main() {let num = Some(4);let split = 5;match num {Some(x) __ => assert!(x < split),Some(x) => assert!(x >= split),None => (),}
}

事实上就是多一个if条件,来进一步匹配而已。

fn main() {let num = Some(4);let split = 5;match num {Some(x) if x < split => assert!(x < split),Some(x) => assert!(x >= split),None => (),}
}

5 🌟🌟🌟 使用 … 忽略一部分值


// 填空,让代码工作
fn main() {let numbers = (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048);match numbers {__ => {assert_eq!(first, 2);assert_eq!(last, 2048);}}
}

可惜只能忽略一次

fn main() {let numbers = (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048);match numbers {(first, .., last) => {assert_eq!(first, 2);assert_eq!(last, 2048);}}
}

6 🌟🌟 使用模式 &mut V 去匹配一个可变引用时,你需要格外小心,因为匹配出来的 V 是一个值,而不是可变引用


// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match r {&mut value => value.push_str(" world!") }
}

思来想去,也只有这一种改法了。

fn main() {let mut v = String::from("hello,");let r = &mut v;match r {value => value.push_str(" world!") }
}

r本身就是对string的可变引用,如果想直接使用的话,没必要再引用一次。按图中的匹配,最后value会是一个不可变string,这样后面的操作就做不到了。

http://www.lryc.cn/news/446043.html

相关文章:

  • 深度学习(4):torch.nn.Module
  • (14)关于docker如何通过防火墙做策略限制
  • 新React开发人员应该如何思考
  • 解密.bixi、.baxia勒索病毒:如何安全恢复被加密数据
  • 开源 AI 智能名片与 S2B2C 商城小程序:嫁接权威实现信任与增长
  • S-Clustr-Simple 飞机大战:骇入现实的建筑灯光游戏
  • MySQL:存储引擎简介和库的基本操作
  • JavaScript类型判断(总结)
  • SpringBoot之登录校验关于JWT、Filter、interceptor、异常处理的使用
  • 我的AI工具箱Tauri版-FunAsr音频转文本
  • C++:模版初阶
  • Python Web 与区块链集成的最佳实践:智能合约、DApp与安全
  • 使用工具将截图公式转换为word公式
  • 深度学习(6):Dataset 和 DataLoader
  • Qt窗口——QToolBar
  • MySQL—存储过程详解
  • 2024ICPC网络赛2记录:CK
  • PerparedStatement概述
  • 联影医疗嵌入式面试题及参考答案(3万字长文)
  • Rust的作用?
  • 无人机之可承受风速的影响因素
  • HTML与JavaScript结合实现简易计算器
  • Docker网络原理
  • PyTorch 目标检测教程
  • 校园美食导航:Spring Boot技术的美食发现之旅
  • 51单片机 - DS18B20实验1-读取温度
  • go语言基础入门(一)
  • linux 基础(一)mkdir、ls、vi、ifconfig
  • DAMODEL丹摩智算:LLama3.1部署与使用
  • Spring Boot 配置全流程 总结