Rust 枚举和模式匹配

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

目录

1、枚举的定义

1.1 Option 枚举和其相对于空值的优势

 2、match 控制流结构

2.1 匹配 Option

2.2 匹配是穷尽的

2.3 通配模式和 _ 占位符

3、if let 简洁控制流


1、枚举的定义

枚举enumerations),也被称作 enums。枚举允许你通过列举可能的 成员variants)来定义一个类型。首先,我们会定义并使用一个枚举来展示它是如何连同数据一起编码信息的。接下来,我们会探索一个特别有用的枚举,叫做 Option,它代表一个值要么是某个值要么什么都不是。然后会讲到在 match 表达式中用模式匹配,针对不同的枚举值编写相应要执行的代码。最后会介绍 if let,另一个简洁方便处理代码中枚举的结构。

下面看下下面这个示例:

#[derive(Debug)]
enum Sex {
    Man,
    Woman,
}
fn main() {
    let var = Sex::Man;
    println!("value is {:?}", var)
}

从上面代码示例中,我们把性别可以枚举出来,引用枚举类型的某一个值的时候,可以通过枚举名后面加一堆冒号来引用枚举中的某一个属性值。

下面这个例子,我们可以在枚举中,它的成员可以有多种类型:

enum op {
    name(String),
    time(i32),
    People { name: String, age: i32 },
}

有关联值的枚举的方式和定义多个不同类型的结构体的方式很相像,除了枚举不使用 struct 关键字以及其所有成员都被组合在一起。

结构体和枚举还有另一个相似点:就像可以使用 impl 来为结构体定义方法那样,也可以在枚举上定义方法。

    enum Op {
        Name(String),
        Time(i32),
        People { name: String, age: i32 },
    }

    impl Op {
        fn say(&self) {}
    }

让我们看看标准库中的另一个非常常见且实用的枚举:Option

1.1 Option 枚举和其相对于空值的优势

这一部分会分析一个 Option 的案例,Option 是标准库定义的另一个枚举。Option 类型应用广泛因为它编码了一个非常普遍的场景,即一个值要么有值要么没值。

例如,如果请求一个非空列表的第一项,会得到一个值,如果请求一个空的列表,就什么也不会得到。从类型系统的角度来表达这个概念就意味着编译器需要检查是否处理了所有应该处理的情况,这样就可以避免在其他编程语言中非常常见的 bug。

编程语言的设计经常要考虑包含哪些功能,但考虑排除哪些功能也很重要。Rust 并没有很多其他语言中有的空值功能。空值Null )是一个值,它代表没有值。在有空值的语言中,变量总是这两种状态之一:空值和非空值。

然而,空值尝试表达的概念仍然是有意义的:空值是一个因为某种原因目前无效或缺失的值。

问题不在于概念而在于具体的实现。为此,Rust 并没有空值,不过它确实拥有一个可以编码存在或不存在概念的枚举。这个枚举是 Option<T>,而且它定义于标准库中,如下:


fn main() {
    enum Option<T> {
        None,
        Some(T),
    }
}

Option<T> 也仍是常规的枚举,Some(T) 和 None 仍是 Option<T> 的成员。<T> 语法是一个我们还未讲到的 Rust 功能。它是一个泛型类型参数,所以你需要知道的就是 <T> 意味着 Option 枚举的 Some 成员可以包含任意类型的数据,同时每一个用于 T 位置的具体类型使得 Option<T> 整体作为不同的类型。这里是一些包含数字类型和字符串类型 Option 值的例子:

 enum Option<T> {
        None,
        Some(T),
    }
 let some_number = Some(5000);
 let some_char = Some('e');
 let some_boolean = Some(true);

让我们再看一下如下示例,定义如下2个值进行相加会怎么样?

fn main() {
    enum Option<T> {
        None,
        Some(T),
    }
    let some_number: i8 = 5;

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

    let plus = some_number + absent_number;
}

运行结果如下所示:

Rust 枚举和模式匹配,Rust,rust,开发语言,后端

在这里有2个严重的问题:

第一个问题是let absent_number: Option<i8> = Some(5); 在这里赋值的时候会报错,这2个类型名看起来很像,但实际上是不同的类型,无法进行赋值操作。

第二个是不同类型进行相加的时候,当在 Rust 中拥有一个像 i8 这样类型的值时,编译器确保它总是有一个有效的值。我们可以自信使用而无需做空值检查。只有当使用 Option<i8>(或者任何用到的类型)的时候需要担心可能没有值,而编译器会确保我们在使用值之前处理了为空的情况。

 2、match 控制流结构

Rust 有一个叫做 match 的极为强大的控制流运算符,它允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面值、变量、通配符和许多其他内容构成;

我们看一下如下示例,能够更清楚的明白match的作用:

fn main() {
    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,
        }
    }
    let res = value_in_cents(Coin::Nickel);
    print!("result {}", res)  // result 5
}

match 的作用,其他跟其他语言(例如,JavaScript)中的switch差不多,以上代码中,方法接收了一个枚举类型,match根据枚举类型的不同成员来返回的不同的值,类似不同的分支,符合条件的分支,才会被最后返回,如果匹配到了某一个分支,想在执行其他逻辑的时候,可以加一对花括号,在里面写对应的逻辑即可。

    fn value_in_cents(coin: Coin) -> u8 {
        match coin {
            Coin::Penny => {
                print!("res: 执行到这了");
                1
            }
            Coin::Nickel => 5,
            Coin::Dime => 10,
            Coin::Quarter => 25,
        }
    }

2.1 匹配 Option<T>

下面编写一个函数,它获取一个 Option<i32> ,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回 None 值。

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);
    println!("{:?}  {:?}   {:?}", five, six, none)  // Some(5)  Some(6)   None

2.2 匹配是穷尽的

match 还有另一方面需要讨论:这些分支必须覆盖了所有的可能性。否则不能进行编译。

fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            Some(i) => Some(i + 1),
        }
    }

Rust 枚举和模式匹配,Rust,rust,开发语言,后端

根据上面错误提示,我们知道Rust中match匹配必须是穷尽的,否则无法编译通过。

2.3 通配模式和 _ 占位符

我们看一下如下示例:

fn main() {
    let dice_roll = 9;
    match dice_roll {
        3 => 3,
        7 => 7,
        hello => 9,
    };
}

3和7会匹配对应的值,定义一个变量例如:hello,则可以匹配其他任意情况下的值。

即使我们没有列出 u8 所有可能的值,这段代码依然能够编译,因为最后一个模式将匹配所有未被特殊列出的值。这种通配模式满足了 match 必须被穷尽的要求。请注意,我们必须将通配分支放在最后,因为模式是按顺序匹配的。如果我们在通配分支后添加其他分支,Rust 将会警告我们,因为此后的分支永远不会被匹配到。

Rust 还提供了一个模式,当我们不想使用通配模式获取的值时,请使用 _ ,这是一个特殊的模式,可以匹配任意值而不绑定到该值。这告诉 Rust 我们不会使用这个值,所以 Rust 也不会警告我们存在未使用的变量。

fn main() {
    let dice_roll = 9;
    match dice_roll {
        3 => 3,
        7 => 7,
        _ => 9,
    };
}

当我们匹配到其他情况,这种情况下我们不想运行任何代码。可以返回一个空元组,如下所示:

fn main() {
    let dice_roll = 9;

    match dice_roll {
        3 => three(),
        7 => seven(),
        _ => (),
    }
    fn three() {}
    fn seven() {}
}

3、if let 简洁控制流

我们先看一个示例:

fn main() {
    let config_max = Some(3u8);
    match config_max {
        Some(max) => println!("The maximum is configured to be {}", max),
        _ => (),
    }
}

如果值是 Some,我们希望打印出 Some 成员中的值,这个值被绑定到模式中的 max 变量里。对于 None 值我们不希望做任何操作。为了满足 match 表达式(穷尽性)的要求,必须在处理完这唯一的成员后加上 _ => (),这样也要增加很多烦人的样板代码。

为了简化代码,可以使用if let 来简化一下:

fn main() {
    let config_max = Some(3u8);
    if let Some(max) = config_max {
        println!("res {}", max)
    }
}

使用 if let 意味着编写更少代码,更少的缩进和更少的样板代码。然而,这样会失去 match 强制要求的穷尽性检查。match 和 if let 之间的选择依赖特定的环境以及增加简洁度和失去穷尽性检查的权衡取舍。

换句话说,可以认为 if let 是 match 的一个语法糖,它当值匹配某一模式时执行代码而忽略所有其他值。

至于下环线匹配的模式,可以通过if let else 来实现,如下所示:文章来源地址https://www.toymoban.com/news/detail-756280.html

fn main() {
    let mut count = 0;
    let config_max = Some(3u8);
    if let Some(max) = config_max {
        println!("res {}", max)
    } else {
        count += 1;
    }
}

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

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

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

相关文章

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

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

    2023年04月22日
    浏览(92)
  • Rust -- 模式与匹配

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

    2023年04月26日
    浏览(38)
  • 【Rust 基础篇】Rust 模式:高效、安全和灵活的匹配工具

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

    2024年02月08日
    浏览(76)
  • RUST 每日一省:模式匹配

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

    2024年02月09日
    浏览(46)
  • 30天拿下Rust之模式与模式匹配

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

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

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

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

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

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

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

    2024年02月12日
    浏览(39)
  • Rust语法: 枚举,泛型,trait

    这是我学习Rust的笔记,本文适合于有一定高级语言基础的开发者看不适合刚入门编程的人,对于一些概念像枚举,泛型等,不会再做解释,只写在Rust中怎么用。 枚举的定义与赋值 枚举的定义格式如下: enum 枚举名{ 值1(附加类型), 值2(附加类型),… } 其中,关联类型可以省去

    2024年02月13日
    浏览(39)
  • Rust语言从入门到入坑——(2)Rust在windows上搭建开发环境

    开始搭建一个适合在windows上运行的Rust环境。 Rust支持的程序语言很多:可详见官网介绍 本文章主要是在windowns下搭建开发环境 首先,需要安装最新版的 Rust 编译工具和 Visual Studio Code。 Rust 编译工具:https://www.rust-lang.org/zh-CN/tools/install Visual Studio Code:https://code.visualstudio.com

    2024年02月09日
    浏览(52)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包