RUST 每日一省:模式匹配

我们经常使用let 语句创建新的变量绑定------但是 let 的功能并不仅限于此。事实上, let 语句是一个模式匹配语句。它允许我们根据内部结构对值进行操作和判断,或者可以用于从代数数据类型中提取值。

rust 复制代码
let tuple = (1_i32, false, 3f32);
let (head, center, tail) = tuple;

如上所示,通过第二句,把一个组合数据结构,拆解开来, 分成了三个不同的变量。在let语句中, =号左边的内容就是模式, =号右边的内容就是需要匹配的内容。 相当于从tuple变量中,提取了三个新的变量head、 center、 tail, 它们分别对应tuple的三个成员。

Rust中模式匹配功能遵循的原则:我们怎么把一个数据结构组合起来的, 我们就怎么把它拆解开来。可以通过下边的例子感受一下rust的美感;

rust 复制代码
struct T1 (i32, char);
struct T2 {
    item1: T1,
    item2: bool,
} 
fn main()
{
    let x = T2 {
        item1: T1(0, 'A'),
        item2: false,
    };
    let T2 {
        item1: T1(value1, value2),
        item2: value3,
    } = x;
    println!("{} {} {}", value1, value2, value3);
}

Rust的"模式匹配"功能出现在let、match、if let、 while let、 函数调用、 闭包调用等情景中。

match

match模式匹配用于流程控制,检查当前值是否匹配一系列模式中的某一个。模式可由字面值、变量、通配符和其他内容构成。每一个模式都是一个分支,程序根据匹配的模式执行相应的代码。

Rust要求match模式匹配是穷尽式的,即必须穷举所有的可能性,否则会导致程序错误。有一个处理方法是将通配符""放置在其他分支之后,通配符""会匹配上面没有指定的所有可能的模式。

  • 竖线(|)可用于在一个 match 分支中组合多个模式;
  • 使用 ... 可以匹配某个范围中的值;
  • 使用操作符@可以将模式中的值绑定给一个变量, 供分支右侧的代码使用, 这类匹配叫绑定模式;使用 if 关键字给 match 分支添加护具。
  • 可以使用if作为"匹配看守"(match guards) 。 当匹配成功且符合if条件, 才执行后面的语句。
  • 通配符"_"会匹配上面没有指定的所有可能的模式。
rust 复制代码
fn main() {
 let age = 6;

 match age {
     0 => println!("You are a baby."),
     1..=7 => println!("You are a toddler."),
     8|9|10|11 => println!("You are a schoolchild."),
     i if i >= 12 && i<=17 => println!("You are a teenager."),
     n @ 18  => println!("You are {}.",n),
     19..=100 => println!("You are an adult."),
     _ => println!("Cool !"),
     }
 }

if let&while let

if let和while let表达式, 在某些场景中可替代match模式匹配来简化代码。

相对于match,if let 可以只匹配我们感兴趣的值,对于剩下情况可以使用else来继续处理。

rust 复制代码
fn main() {
 let value =  Some(7);
 if let Some(7) = value {
     println!("seven"); }

  if let Some(v) = value {
     println!("Some({})",v); 
  }else{
     println!("None"); 
  }

 }

条件循环while let,它会反复执行同一个模式匹配直到出现失败的情形。

rust 复制代码
fn while_let_vec() {
 let mut vec = vec![1, 2, 3, 4, 5];
 while let Some(value) = vec.pop() { 
    println!("{}", value);
 }
 }

函数参数(闭包)

通过上边两种情况,估计你已经大概有一个了解了,我们就直接看例子吧。

rust 复制代码
struct T {
    item1: char,
    item2: bool,
} 
fn test( T{item1: arg1, item2: arg2} : T) {
    println!("{} {}", arg1, arg2);
} 
fn main()
{
    let x = T {
        item1: 'A',
        item2: false,
    };
    test(x);
}

类似于函数的参数列表,我们同样可以在闭包的参数列表中使用模式。

其他(let,for)

还有一些场景我们可能也会遇到,不过如果你已经理解了模式匹配的规律,不论是看到还是写相关的代码,估计也是信手拈来。

let文章开始就已经介绍了, for可以看一下例子,是不是很自然。

rust 复制代码
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
    println!("{} is at index {}", value, index);
}
相关推荐
深邃-6 分钟前
【Web安全】-基础环境安装:虚拟机安装,JDK环境安装(1)
java·开发语言·计算机网络·安全·web安全·网络安全·安全架构
前端老石人9 分钟前
前端网站换肤功能的 3 种实现方案
开发语言·前端·css·html
Legendary_00810 分钟前
LDR6500U PD取电芯片:赋能设备Type-C升级,解锁高效安全取电新体验
c语言·开发语言·安全
bilI LESS10 分钟前
数据库操作与数据管理——Rust 与 SQLite 的集成
数据库·rust·sqlite
Rust研习社15 分钟前
深入理解 Rust 裸指针:内存操作的双刃剑
开发语言·后端·rust
Huangjin007_16 分钟前
【C++ STL篇(四)】一文拿捏vector常用接口!
开发语言·c++·学习
NQBJT18 分钟前
[特殊字符] VS Code + Markdown 从入门到精通:写论文、技术文档的超实用指南
开发语言·vscode·c#·markdown
草莓熊Lotso19 分钟前
Linux 线程同步与互斥(一):彻底搞懂线程互斥原理、互斥量底层实现与 RAII 封装
linux·运维·服务器·开发语言·数据库·c++
逻辑驱动的ken21 分钟前
Java高频面试场景题07
java·开发语言·面试·职场和发展·求职招聘·春招
我不是懒洋洋28 分钟前
【数据结构】栈和链表基本方法的实现
c语言·开发语言·数据结构·c++·链表·青少年编程·ecmascript