美文网首页
Rust语言教程(9) - if let表达式与枚举进阶

Rust语言教程(9) - if let表达式与枚举进阶

作者: Jtag特工 | 来源:发表于2022-10-12 03:35 被阅读0次

Rust语言教程(9) - if let表达式与枚举进阶

枚举复习

前面我们介绍了Rust中的枚举类型,以及通过枚举实现的Option, Result等类型。
温故而知新,我们再来复习一下枚举的定义和使用。

首先,Rust的enum可以像C语言中的enum一样,定义一组可枚举的常量值。比如我们可以这样描述带符号的整数:

enum Integers{
    Int8,
    Int16,
    Int32,
    Int64,
    Int128,
    Bigint
}

我们在使用时可以将常量转换为整数来使用,例如:

    let int1 = Integers::Int8;
    println!("{}",(int1 as i32));

如同C语言一样,Rust的enum常量也可以指定值:

enum Integers{
    Int8=1,
    Int16,
    Int32,
    Int64,
    Int128,
    Bigint
}

除了可以定义常量枚举,Rust还可以定义带有变量的枚举。例如,我们想描述一个8位的整数,它可以是有符号的,也可以是无符号的,我们可以这样定义:

enum Bits8 {
    Uint8(u8),
    Int8(i8)
}

我们就可以用这个Bits8枚举用来既能表示有符号的8位整数,也可以表示无符号的8位整数。为了共享,我们再加上前一节学的Box包装一下:

    let bit1 = Box::new(Bits8::Uint8(1u8));
    let bit2 = Box::new(Bits8::Int8(-2i8));

对于枚举的变量,我们可以通过match模式匹配的方法来对其进行计算。例如:

    match *bit1 {
        Bits8::Uint8(value) => println!("unsinged int:{}",value),
        Bits8::Int8(value) => println!("signed int:{}",value)
    }

当然,针对不匹配的情况,也可以什么也不错。这时候可以使用"_"来匹配不想处理的所有情况:

    match *bit2 {
        Bits8::Int8(value) => println!("signed int:{}",value),
        _ => {}
    }

if let表达式

因为match表达式要符合MECE原则,所以必须要处理所有的情况。为了代码写起来方便,像Rust和Swift这样的现代语言都实现了if let表达式。
以上面的例子为例,我们的if let表达式可以写为:

    if let Bits8::Uint8(value) = *bit1 {
        println!("unsinged int:{}",value);
    }

if let表达式当然也支持else:

        if let Bits8::Uint8(value) = *bit1 {
            println!("unsinged int:{}",value);
        } else {
            println!("not unsinged int");
        }

我们将bit1改成bit2,就会走else分支。

if let表达式最常用的情况就是在Option或者Result中使用。

比如我们将一个整数放到Option中,然后打包到Box里面:

let num1 = Box::new(Some(1i32));

如果要用到包装的值,暴力的作法是直接unwrap:

let num2 = num1.unwrap() + 1i32;

但是这样的话,如果num1是None的话,就会panic。所以我们可以用if let来判断一下:

    if let Some(num3) = *num1 {
        let num4 = num3 + 2i32;
        println!("{} {} {}",num2,num3,num4);
    }

我们再看一个例子,将Option转化为Result:

fn test(i:Option<Box<i32>>) -> Result<Box<i32>, &'static str>{
    match i{
        Some(i) => Ok(i),
        None => Err("NAN")
    }
}

为枚举定义方法

以前面的Integers为例,我们不想将类型常量转换为整数来使用,而是想直接使用它们。这时我们可以为枚举定义方法,就像给struct定义方法一样,仍然使用impl关键字来实现。比如我们可以实现Display方法,来让它们可以直接打印:

impl Display for Integers{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", (*self as i32))
    }
}

针对带变量值的枚举类型,为其定义函数的作用将更大。

比如我们前面定义的统一的8位有符号和无符号整数的枚举值,我们现在就可以为其定义算数运算了。

impl Add for Bits8{
    type Output = Self;
    fn add(self, other: Self) -> Self::Output {
        match (self, other) {
            (Bits8::Uint8(a), Bits8::Uint8(b)) => Bits8::Uint8(a + b),
            (Bits8::Int8(a), Bits8::Int8(b)) => Bits8::Int8(a + b),
            (Bits8::Uint8(a), Bits8::Int8(b)) => Bits8::Int8(a as i8 + b),
            (Bits8::Int8(a), Bits8::Uint8(b)) => Bits8::Int8(a + b as i8),
        }
    }
}

Add是对应“+”的trait,我们可以为Bits8实现Add,然后就可以直接使用“+”了。

    let bit4 = Box::new(Bits8::Uint8(1));
    let bit5 = Box::new(Bits8::Int8(-1));
    let bit6 = *bit4 + *bit5;
    println!("bit6:{}",bit6);

我们还可以使用上节学习的Arc将枚举值封装到多线程共享的变量中,这时在进行加法之前我们先将其borrow出来:

    let bit4 = Arc::new(Bits8::Uint8(1));
    let bit5 = Arc::new(Bits8::Int8(-1));
    let b4: &Bits8= bit4.borrow();
    let b5: &Bits8= bit5.borrow();
    let b6 = b4 + b5;
    println!("Arc:{:?}",b6);

borrow出来的结果是引用,没法使用上面针对于Bits8的Add方法,所以我们需要再定义一个Add方法,针对于引用。
返回值的时候我们就不要返回引用了,将其分配到Arc中再返回:

impl Add for &Bits8{
    type Output = Arc<Bits8>;
    fn add(self, other: Self) -> Self::Output {
        match (self, other) {
            (Bits8::Uint8(a), Bits8::Uint8(b)) => Arc::new(Bits8::Uint8(a + b)),
            (Bits8::Int8(a), Bits8::Int8(b)) => Arc::new(Bits8::Int8(a + b)),
            (Bits8::Uint8(a), Bits8::Int8(b)) => Arc::new(Bits8::Int8((*a) as i8 + b)),
            (Bits8::Int8(a), Bits8::Uint8(b)) => Arc::new(Bits8::Int8(a + (*b) as i8)),
        }
    }
}

小结

Rust的枚举是可以定义方法的,这样会大大有助于我们像使用struct一样使用枚举。
另外,if let也是非常有用的,可以让我们在不使用match的情况下,对枚举值进行判断和处理,可以大大简化代码,提升编程效率。
同样,也有while let这样的语法糖。

相关文章

  • Rust语言教程(9) - if let表达式与枚举进阶

    Rust语言教程(9) - if let表达式与枚举进阶 枚举复习 前面我们介绍了Rust中的枚举类型,以及通过枚...

  • Rust语言教程(3) - 数组与向量

    Rust语言教程(3) - 数组与向量 上一节我们采摘了不少低矮的果实,将其它语言学到的知识迁移到Rust 中来。...

  • Rust语言教程(6) - 错误处理和可选值

    Rust语言教程(6) - 错误处理和可选值 Rust的错误处理 从前面的学习中,我们对于Rust的错误处理应该已...

  • 正则表达式01

    正则表达式根据李炎灰视频教程总结 创建正则表达式有两种方式字面量的方式let box = 'box';let pa...

  • Rust 枚举

    枚举 枚举,也被称作enums。枚举允许你通过列举可能的值来定义一个类型。 定义枚举 枚举值 可以使用任一成员来调...

  • Rust 学习资源

    Rust编程语言 Rust编程语言(https://doc.rust-lang.org/book/[https:/...

  • gis教程链接

    QGIS教程:入门与进阶 — QGIS教程:入门与进阶 QGIS 3.x 入门教程—数据可视化 - 网易云课堂 S...

  • 读Rust程序设计语言 - 03

    语言/Rust 变量与可变性 - Rust 程序设计语言 简体中文版 变量和可变性 在rust中变量是默认不可变的...

  • Rust 中的 if let 与 while let

    上述语句明显是合理的,但我们接着往下看: if let是可以在普通if中使用的,那我们换一种想法 不将if let...

  • rust语句1

    常用的语言,表达式语句是语言的组成部分,rust也是一样的。 if语句 和C语言并无区别 循环语句 c、c++中的...

网友评论

      本文标题:Rust语言教程(9) - if let表达式与枚举进阶

      本文链接:https://www.haomeiwen.com/subject/bruzartx.html