使用 Rust 的 let-else 实现简洁的模式匹配

Beginner

This tutorial is from open-source community. Access the source code

简介

在本实验中,将演示 Rust 中 let-else 的用法。其中,可反驳模式能够匹配并绑定周围作用域中的变量,若模式不匹配,则可通过使用 breakreturnpanic! 等语句来使程序发散。在处理模式匹配和错误处理场景时,这种结构能让代码简洁且易读,无需重复代码块或使用外部 let 语句。

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,并通过 rustc main.rs &&./main 进行编译和运行。

使用 let-else

借助 let-else,可反驳模式能够像普通的 let 一样匹配并绑定周围作用域中的变量,若模式不匹配,则会发散(例如 breakreturnpanic!)。

use std::str::FromStr;

fn get_count_item(s: &str) -> (u64, &str) {
    let mut it = s.split(' ');
    let (Some(count_str), Some(item)) = (it.next(), it.next()) else {
        panic!("无法分割计数 - 物品对:'{s}'");
    };
    let Ok(count) = u64::from_str(count_str) else {
        panic!("无法解析整数:'{count_str}'");
    };
    (count, item)
}

fn main() {
    assert_eq!(get_count_item("3 chairs"), (3, "chairs"));
}

名称绑定的作用域是它与 matchif let-else 表达式的主要区别所在。以前,你可能需要通过一些不太优雅的重复代码和外部 let 来近似实现这些模式:

use std::str::FromStr;

fn get_count_item(s: &str) -> (u64, &str) {
    let mut it = s.split(' ');
    let (count_str, item) = match (it.next(), it.next()) {
        (Some(count_str), Some(item)) => (count_str, item),
        _ => panic!("无法分割计数 - 物品对:'{s}'"),
    };
    let count = if let Ok(count) = u64::from_str(count_str) {
        count
    } else {
        panic!("无法解析整数:'{count_str}'");
    };
        (count, item)
    }

    assert_eq!(get_count_item("3 chairs"), (3, "chairs"));

总结

恭喜你!你已完成“Let-Else”实验。你可以在 LabEx 中练习更多实验来提升你的技能。