【Rust】——枚举与模式匹配

Y小夜 2024-07-30 14:35:01 阅读 88

🎃个人专栏:

🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客

🐳Java基础:Java基础_IT闫的博客-CSDN博客

🐋c语言:c语言_IT闫的博客-CSDN博客

🐟MySQL:数据结构_IT闫的博客-CSDN博客

🐠数据结构:​​​​​​数据结构_IT闫的博客-CSDN博客

💎C++:C++_IT闫的博客-CSDN博客

🥽C51单片机:C51单片机(STC89C516)_IT闫的博客-CSDN博客

💻基于HTML5的网页设计及应用:基于HTML5的网页设计及应用_IT闫的博客-CSDN博客​​​​​​

🥏python:python_IT闫的博客-CSDN博客

🐠离散数学:离散数学_IT闫的博客-CSDN博客

​​​​​​🥽Linux:​​​​Linux_Y小夜的博客-CSDN博客

🚝Rust:Rust_Y小夜的博客-CSDN博客

欢迎收看,希望对大家有用!

目录

🎯定义枚举

 🎯Option枚举

🥽类似Null概念的枚举—Option

🎯控制流运算符-match

 🥽绑定值得模式:

🥽匹配Option

🥽match匹配必须穷举所有的可能

🥽通配符

🎯if let


学习推荐:

        在当今这个飞速发展的信息时代,人工智能(AI)已经成为了一个不可或缺的技术力量,它正在逐步改变着我们的生活、工作乃至整个社会的运作方式。从智能语音助手到自动驾驶汽车,从精准医疗到智慧城市,人工智能的应用已经渗透到了我们生活的方方面面。因此,学习和掌握人工智能相关的知识和技能,对于任何希望在这个时代保持竞争力的个人来说,都已经变得至关重要。

        然而,人工智能是一个涉及数学、计算机科学、数据科学、机器学习、神经网络等多个领域的交叉学科,其学习曲线相对陡峭,对初学者来说可能会有一定的挑战性。幸运的是,随着互联网教育资源的丰富,现在有大量优秀的在线平台和网站提供了丰富的人工智能学习材料,包括视频教程、互动课程、实战项目等,这些资源无疑为学习者打开了一扇通往人工智能世界的大门。

        前些天发现了一个巨牛的人工智能学习网站:前言 – 人工智能教程通俗易懂,风趣幽默,忍不住分享一下给大家。

🎯定义枚举

枚举:

允许我们列举所有可能的值来定义一个类型。

如:

定义一个 <code>IpAddrKind 枚举来表现这个概念并列出可能的 IP 地址类型,V4 和 V6。这被称为枚举的 成员variants):

enum IpAddrKind {

V4,

V6,

}

枚举值:

    let four = IpAddrKind::V4;

    let six = IpAddrKind::V6;

        注意枚举的成员位于其标识符的命名空间中,并使用两个冒号分开。这么设计的益处是现在 IpAddrKind::V4 和 IpAddrKind::V6 都是 IpAddrKind 类型的。

fn route(ip_kind: IpAddrKind) {}

现在可以使用任一成员来调用这个函数:

route(IpAddrKind::V4);

route(IpAddrKind::V6);

将数据附加到枚举的变体中:

enum IpAddr {

V4(String),

V6(String),

}

let home = IpAddr::V4(String::from("127.0.0.1"));

let loopback = IpAddr::V6(String::from("::1"));

优点:

直接将数据附加到枚举的每个成员上,这样就不需要一个额外的结构体每个成员可以处理不同类型和数量的数据。

如:

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),

}

Quit 没有关联任何数据。Move 类似结构体包含命名字段。Write 包含单独一个 StringChangeColor 包含三个 i32

为枚举定义方法:

例子:

impl Message {

fn call(&self) {

// 在这里定义方法体

}

}

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

m.call();

 🎯Option枚举

Option 是标准库定义的另一个枚举。在Prelude(预导入模块中)描述了:某个可能存在(某种类型)或不存在的情况。

Rust 并没有很多其他语言中有的空值功能。空值Null )是一个值,它代表没有值。

Null引用:The Billion Dollar MistakeNull的问题在于:当尝试像使用非Null值那样使用Null值的时候,就会引起某种错误。Null的概念还是有用的,因某种原因变为无效或缺失的值。

🥽类似Null概念的枚举—Option<T>

enum Option<T> {

None,

Some(T),

}

它包括在Prelude(与导入模块)中。可直接使用:

        —Option<T>

        —Some(T)

        —None

可以不需要 Option:: 前缀来直接使用。

例子:

let some_number = Some(5);

let some_char = Some('e');

let absent_number: Option<i32> = None;

        Rust 需要我们指定 Option 整体的类型,因为编译器只通过 None 值无法推断出 Some 成员保存的值的类型。这里我们告诉 Rust 希望 absent_number 是 Option<i32> 类型的。

        简而言之,因为 Option<T> 和 T(这里 T 可以是任何类型)是不同的类型,编译器不允许像一个肯定有效的值那样使用 Option<T>

如:

let x: i8 = 5;

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

let sum = x + y;

会出现类型不匹配的错误。

若想使用Option<T>中的T,必须将它转化为T。

🎯控制流运算符-match

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

例子:

enum Coin {

Penny,

Nickel,

Dime,

Quarter,

}

fn value_in_cents(coin: Coin) -> u8 {

match coin {

Coin::Penny => 1,

Coin::Nickel => 5,

Coin::Dime => 10,

Coin::Quarter => 25,

}

}

 🥽绑定值得模式:

例子:

#[derive(Debug)] // 这样可以立刻看到州的名称

enum UsState {

Alabama,

Alaska,

// --snip--

}

enum Coin {

Penny,

Nickel,

Dime,

Quarter(UsState),

}

fn value_in_cents(coin: Coin) -> u8 {

match coin {

Coin::Penny => 1,

Coin::Nickel => 5,

Coin::Dime => 10,

Coin::Quarter(state) => {

println!("State quarter from {:?}!", state);

25

}

}

}

        在这些代码的匹配表达式中,我们在匹配 Coin::Quarter 成员的分支的模式中增加了一个叫做 state 的变量。当匹配到 Coin::Quarter 时,变量 state 将会绑定 25 美分硬币所对应州的值。接着在那个分支的代码中使用 state。

🥽匹配Option<T>

fn plus_one(x: Option<i32>) -> Option<i32> {

match x {

None => None,

Some(i) => Some(i + 1),

}

}

let five = Some(5);

let six = plus_one(five);

let none = plus_one(None);

        比如我们想要编写一个函数,它获取一个 Option<i32> ,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回 None 值,而不尝试执行任何操作。

🥽match匹配必须穷举所有的可能

fn plus_one(x: Option<i32>) -> Option<i32> {

match x {

Some(i) => Some(i + 1),

}

}

没有处理 None 的情况,所以这些代码会造成一个 bug

🥽通配符

let dice_roll = 9;

match dice_roll {

3 => add_fancy_hat(),

7 => remove_fancy_hat(),

_ => (),

}

fn add_fancy_hat() {}

fn remove_fancy_hat() {}

如果你掷出 3 或 7 以外的值,你的回合将无事发生。

🎯if let

  if let 语法获取通过等号分隔的一个模式和一个表达式。它的工作方式与 match 相同,这里的表达式对应 match 而模式则对应第一个分支。

        但是,这样会失去 match 强制要求的穷尽性检查。match 和 if let 之间的选择依赖特定的环境以及增加简洁度和失去穷尽性检查的权衡取舍。

let config_max = Some(3u8);

if let Some(max) = config_max {

println!("The maximum is configured to be {}", max);

}

等价于

let config_max = Some(3u8);

match config_max {

Some(max) => println!("The maximum is configured to be {}", max),

_ => (),

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。