rust学习-枚举和模式匹配

这篇具有很好参考价值的文章主要介绍了rust学习-枚举和模式匹配。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

枚举

从ip地址入手学枚举
枚举的每个成员可以处理不同类型和数量的数据

初版

enum IpAddrKind {
    V4,
    V6,
}

struct IpAddr {
    kind: IpAddrKind,
    address: String,
}

let home = IpAddr {
    kind: IpAddrKind::V4,
    address: String::from("127.0.0.1"),
};

let loopback = IpAddr {
    kind: IpAddrKind::V6,
    address: String::from("::1"),
};

第二版

enum IpAddr {
    V4(String),
    V6(String),
}

// 直接将数据附加到枚举的每个成员上
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));

第三版

使用枚举来存储两种不同 IP 地址的几种可能的选择

enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));

第四版-标准库

可以将任意类型的数据放入枚举成员中,甚至枚举中放枚举
虽然标准库中包含一个 IpAddr 的定义,仍然可以创建和使用自己的定义而不会有冲突,因为并没有将标准库中的定义引入作用域


struct Ipv4Addr {
    // --snip--
}

struct Ipv6Addr {
    // --snip--
}

enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}

其他示例

枚举实现
枚举是单独一个类型

enum Message {
    Quit, // 没有关联任何数据
    Move { x: i32, y: i32 }, // 包含一个匿名结构体
    Write(String),
    ChangeColor(i32, i32, i32),
}

结构体实现
结构体是各是各的类型

struct QuitMessage; // 类单元结构体
struct MoveMessage {
    x: i32,
    y: i32,
}
struct WriteMessage(String); // 元组结构体
struct ChangeColorMessage(i32, i32, i32); // 元组结构体

和结构体的相似点:在枚举上定义方法

impl Message {
    fn call(&self) {
        // 在这里定义方法体
    }
}

let m = Message::Write(String::from("hello"));
m.call();

Option枚举

标准库定义的枚举
它编码了一个非常普遍的场景,即一个值要么有值要么没值
空值是一个因为某种原因目前无效或缺失的值
Rust 没有空值功能
空值带来的问题:像一个非空值那样使用一个空值,出现错误

Rust的设计:一个可以编码存在或不存在概念的枚举
它被包含在 prelude 之中,不需要将其显式引入作用域
它的成员也可以不需要 Option:: 前缀来直接使用 Some 和 None

// <T>是泛型
// <T> 意味着 Option 枚举的 Some 成员可以包含任意类型的数据
enum Option<T> {
    Some(T),
    None,
}

let some_number = Some(5);
let some_string = Some("a string");
// 如果使用 None,需要告诉 Rust Option<T> 是什么类型
// 编译器只通过 None 值无法推断出 Some 成员保存的值的类型
let absent_number: Option<i32> = None;

Option 为什么就比空值要好呢?
Option 和 T(这里 T 可以是任何类型)是不同的类型
编译器不允许像一个肯定有效的值那样使用 Option
当在 Rust 中拥有一个像 i8 这样类型的值时,编译器确保它总是有一个有效的值。可以自信使用而无需做空值检查。
只有当使用 Option(或者任何用到的类型)的时候需要担心可能没有值,而编译器会确保在使用值之前处理了为空的情况。
在对 Option 进行 T 的运算之前必须将其转换为 T,通常这能捕获到空值最常见的问题之一:假设某值不为空但实际上为空的情况

let x: i8 = 5;
let y: Option<i8> = Some(5);
let sum = x + y;

限制空值泛滥,增加 Rust 代码安全性

为了拥有一个可能为空的值,必须要显式的将其放入对应类型的 Option 中。当使用这个值时,必须明确地处理值为空的情况。
为了使用 Option 值,需要编写处理每个成员的代码。
想要一些代码只当拥有 Some(T) 值时运行,允许这些代码使用其中的 T。希望一些代码在值为 None 时运行,这些代码并没有一个可用的 T 值。

match 表达式就是这么一个处理枚举的控制流结构:
它会根据枚举的成员运行不同的代码,
这些代码可以使用匹配到的值中的数据

match 控制流运算符

将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码
模式可由字面量、变量、通配符和许多其他内容构成

示例

#[derive(Debug)] // 这样可以立刻看到州的名称
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

// 当 match 表达式执行时,它将结果值按顺序与每一个分支的模式相比较。
// 如果模式匹配了这个值,这个模式相关联的代码将被执行。如果模式并不匹配这个值,将继续执行下一个分支
fn value_in_cents(coin: Coin) -> u8 {
	// 在分支中运行多行代码,可以使用大括号
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        // 可以绑定匹配的模式的部分值。这也就是如何从枚举成员中提取值
        // 调用 value_in_cents(Coin::Quarter(UsState::Alaska)),state 绑定的将会是值 UsState::Alaska
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

匹配 Option

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
    	// 匹配是有穷的,如果下面二缺一,则编译不过,Rust 知道哪些模式被忘记了
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);         // 匹配Some(i) => Some(i + 1),
let none = plus_one(None)   // 匹配None => None

通配模式

想使用通配模式获取的值

let dice_roll = 9;
match dice_roll {
	// 对一些特定的值采取特殊操作,而对其他的值采取默认操作
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    // 通配模式满足了 match 必须被穷尽的要求
    other => move_player(other),  // 通配所有其他模式
    // 必须将通配分支放在最后,因为模式是按顺序匹配的。如果在通配分支后添加其他分支,则永远也不会被执行
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}

_ 占位符

不想使用通配模式获取的值

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    _ => reroll(),  // 占位
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn reroll() {}

可以使用单元值(空元组)作为 _ 分支的代码

let dice_roll = 9;
match dice_roll {
    3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    _ => (),
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}

简单控制流

背景

let some_u8_value = Some(0u8);
match some_u8_value {
    Some(3) => println!("three"),
    _ => (),   // 如果只想处理 Some(3),但是不处理其他的,则代码中太多冗余这种行
}

解决

失去 match 强制要求的穷尽性检

if let Some(3) = some_u8_value {
    println!("three");
}

// 如下两个示例等价
let mut count = 0;
match coin {
    Coin::Quarter(state) => println!("State quarter from {:?}!", state),
    _ => count += 1,
}

let mut count = 0;
if let Coin::Quarter(state) = coin {
    println!("State quarter from {:?}!", state);
} else {
    count += 1;
}

总结

当枚举值包含数据时,可以根据需要处理多少情况来选择使用 match 或 if let 来获取并使用。文章来源地址https://www.toymoban.com/news/detail-570115.html

到了这里,关于rust学习-枚举和模式匹配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust编程语言入门之模式匹配

    模式是Rust中的一种特殊语法,用于匹配复杂和简单类型的结构 将模式与匹配表达式和其他构造结合使用,可以更好地控制程序的控制流 模式由以下元素(的一些组合)组成: 字面值 解构的数组、enum、struct 和 tuple 变量 通配符 占位符 想要使用模式,需要将其与某个值进行

    2023年04月22日
    浏览(79)
  • 【Rust】Rust学习 第十八章模式用来匹配值的结构

    模式是 Rust 中特殊的语法,它用来匹配类型中的结构,无论类型是简单还是复杂。结合使用模式和  match  表达式以及其他结构可以提供更多对程序控制流的支配权。模式由如下一些内容组合而成: 字面值 解构的数组、枚举、结构体或者元组 变量 通配符 占位符 这些部分描

    2024年02月11日
    浏览(31)
  • Rust -- 模式与匹配

    1. 模式 匹配类型中的结构(数据的形状),结合 模式和match表达式 提供程序控制流的支配权 模式组成内容 字面量 解构的数组、枚举、结构体、元组 变量 通配符 占位符 流程:匹配值 -- 是否拥有正确的数据 -- 运行特定的代码 2. 使用模式的位置 match分支:由match、一个匹

    2023年04月26日
    浏览(26)
  • 30天拿下Rust之模式与模式匹配

    概述         Rust语言以其强大的类型系统和所有权模型而著称,而模式与模式匹配则是Rust中一种非常强大且灵活的工具,它允许我们在编译时根据数据的结构进行条件分支处理。在Rust中,模式是一种用于匹配数据的结构,它可以是一个具体的值、一个变量绑定、一个枚

    2024年04月12日
    浏览(32)
  • RUST 每日一省:模式匹配

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

    2024年02月09日
    浏览(27)
  • 【Rust 基础篇】Rust 模式:高效、安全和灵活的匹配工具

    在编程中,经常需要对数据进行匹配和处理,例如从一个复杂的数据结构中提取特定的值,或者根据不同的情况执行不同的逻辑。Rust是一门现代的系统编程语言,它引入了一种称为\\\"模式\\\"(Pattern)的强大特性,使得数据的匹配和处理变得高效、安全和灵活。本篇博客将深入探

    2024年02月08日
    浏览(43)
  • 【跟小嘉学 Rust 编程】十八、模式匹配(Patterns and Matching)

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月11日
    浏览(29)
  • C语言学习笔记:枚举(enum)

    ✨博文作者:烟雨孤舟 💖 喜欢的可以 点赞 收藏 关注哦~~ ✍️ 作者简介: 一个热爱大数据的学习者 ✍️ 笔记简介:作为大数据爱好者,以下是个人总结的学习笔记,如有错误,请多多指教! 目录 简介 枚举定义 枚举变量的定义 枚举的应用 枚举enum是英文enumerate的缩写,列

    2024年02月09日
    浏览(29)
  • 【Rust 基础篇】Rust 枚举类型

    在 Rust 中,枚举类型(Enum)是一种自定义数据类型,它允许我们定义一个值只能取自预定义列表中的变量。枚举类型在编写代码时可以提供更明确的语义,使得代码更易于理解和维护。本篇博客将详细介绍 Rust 中的枚举类型,包括定义、使用和模式匹配等方面的内容。 在

    2024年02月12日
    浏览(27)
  • rust学习-模式

    模式由如下一些内容组合而成 (1)字面量 (2)解构的数组、枚举、结构体或者元组 (3)变量 (4)通配符 (5)占位符 match 表达式必须是 穷尽(exhaustive) 模式 _ 可以匹配所有情况,不过它从不绑定任何变量,忽略任何未指定值的情况很有用 if let 表达式的缺点: 其穷尽

    2024年02月15日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包