模式匹配

模式

模式是 Rust 中的特殊语法,它用来匹配类型中的结构,无论类型是简单还是复杂。结合使用模式和 match 表达式以及其他结构可以提供更多对程序控制流的支配权。

模式由以下内容组成:

  • 字面值
  • 已解构的数组、枚举、结构体或元组
  • 变量
  • 通配符
  • 占位符

所有可能会用到模式的位置

match 分支

在形式上 match 表达式由 match 关键字、用于匹配的值和一个或多个分支构成,这些分支包含一个模式和在值匹配分支的模式时运行的表达式,如下所示:

#![allow(unused)]
fn main() {
match {
    pattern => expression,
    pattern => expression,
    pattern => expression,
}
}

NoneSome(i)

#![allow(unused)]
fn main() {
match x {
    None => None,
    Some(i) => Some(i + 1),
}
}

if let 条件表达式

只关心一个情况的 match 表达式的简写。可以组合并匹配 if letelse ifelse if let 并不要求他们互相关联。

while let 条件循环

只要模式匹配就一直执行 while 循环。

for 循环

let 语句

#![allow(unused)]
fn main() {
let PATTERN = EXPRESSION;
}

变量名位于 PATTERN 所的位置,变量名是形式特别朴素的模式。我们将表达式与模式比较,并为任何找到的名称赋值。let x = 5 中 , x 代表的是 “将匹配到的值绑定到变量 x” 的模式。同时因为 x 是整个模式,这个模式实际上等于 “将任何值绑定到变量x,不管值是什么”。

函数参数

函数参数也可以是模式。

可反驳性

Refutability (可反驳性)模式是否会匹配失效。

模式有两种模式:refutable (可反驳的)和 irrefutable (不可反驳的)。能匹配任何传递的可能值的模式被称为是“不可反驳的(irrefutable)”。 对某些可能的值进行匹配会失败的模式被称为是 “可反驳的(refutable)”。

函数参数 、 let、 for 只能接受不可反驳模式,if let 、while let 可以接受可反驳和不可反驳的。

模式语法

匹配字面值

fn main() {
    let x = 7;
    match x {
        1 => println!("one"),               // 普通字面值
        2 | 3 => println!("two or three"),  // 多个模式
        4..=5 => println!("4-5"),           // 范围范围-右闭区间
        6..7 => println!("6"),              // 匹配范围-右开区间
        other => println!("other {other}"), // 匹配剩余并绑定变量
        _ => println!("other"),             // 匹配剩余不绑定变量
    }
}

匹配命名变量

fn main() {
    let x = Some(5);
    let y = 10;
    match x {
        Some(50) => println!("Got 50"),
        Some(y) => println!("y = {y}"),
        _ => println!("default case x={:?}", x),
    }

    println!("main y={}", y);
}

解构结构体

struct Point {
    x: u32,
    y: u32,
}
fn main() {
    let point = Point { x: 1, y: 2 };
    let Point { x: a, y: b } = point;
    println!("a = {} b = {}", a, b);
}

解构枚举

use std::arch::x86_64;

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
fn main() {
    let message = Message::ChangeColor(0, 160, 255);
    match message {
        Message::Quit => println!("Quit"),
        Message::Move { x, y } => println!("Move: {x}{y}"),
        Message::Write(s) => println!("Write: {s}"),
        Message::ChangeColor(r, g, b) => println!("ChangeColor {r} {g} {b}")
    }
}

解构结构体和枚举嵌套

匹配守卫

fn main() {
    // let num = Some(6);
    let num = None::<i32>;
    match num {
        Some(x) if x < 5 => println!("less than five: {x}"),
        Some(x) => println!("{x}"),
        None => (),
    }
}

@绑定

fn main() {
    enum Message {
        Hello { id: i32 },
    }

    let message = Message::Hello{id: 12};
    match message {
        Message::Hello { 
            id: id_var @3..7,
         } => {
            println!("id_var: {}", id_var);
        },
        Message::Hello { id: 10..=12 } => {
            println!("10~12");
        }
        Message::Hello { id } => {
            println!("id {}", id)
        }
    }

}