首页 > 其他分享 >rust学习七、枚举

rust学习七、枚举

时间:2024-11-11 18:19:01浏览次数:1  
标签:学习 枚举 let rust println Coin match

枚举是十分特别的类型,是因为和大部分语言中看起来不太一样。

最大的不同之一在于:允许每个成员具有不同的类型的属性

 

注:本文内容根据<<The rust programmming Language>>有关章节编写

如果没有特别说明,"rust学习"系列基本上都是根据此书编写,不再在后续的篇幅中说明

一、定义、赋值和打印

结论:

1.rust枚举类型相当之怪异 2.枚举的定义中,允许成员包含数据,也可以不包含数据。 3.当枚举类型中包含数据时,不同的枚举实例还可以包含不同的类型的数据。 4.枚举的成员只能包含(a-z, A-Z)、数字(0-9)、下划线(_)以及 Unicode 非字母数字字符    不能以数字开头    当每个枚举成员都可以不同的时候,我们把它理解成java的Object类型即可。  总之,rust的枚举类型极其怪,不同于于其它语言     枚举的定义中,枚举成员的命名方式为:首字母大写(仅仅是建议) 5.枚举可以有方法,和struct结构类似,定义的方式也类似,放在枚举外,而不是在内部  

示例

#[derive(Debug)]
enum simple_enum {
    Man,
    Women,
    Other
}

//b. 枚举类型中包含数据
#[derive(Debug)]
enum color {
    Red,
    Green = 3
}

//c.枚举类型中包含多个数据,且都是一样的
#[derive(Debug)]
#[derive(PartialEq)]
enum grade {
    A(u32,String),
    B(u32,String),
    C(u32,String)
}

//枚举的方法,定义上了struct方法类似,都是impl,&self
impl grade {
    fn print(&self) {   
        //这个tmd也太麻烦了吧
        match self {
            grade::A(a,b) => println!("{}-{}",a,b),
            grade::B(a,b) => println!("{}-{}",a,b),
            grade::C(a,b) => println!("{}-{}",a,b)
        }
    }
}

#[derive(Debug)]
enum food<'a>{
    蔬菜([String;5]),
    禽肉,
    猪肉,
    牛羊肉,
    海鲜,
    大米,
    水果(&'a str,&'a str,&'a str)
}

fn main() {
    let a = simple_enum::Man;
    println!("{:?}",a);
    // 使用println! :?宏打印枚举的时候,变量名称不能同枚举成员。否则会报错
    let gr = color::Green;  
    println!("{:?}",gr);
    let r = color::Red;
    println!("{:?}",r);

    let grade_a = grade::A(10,String::from("差"));
    let grade_a1=grade::A(9,String::from("差011"));
    grade_a.print();
    println!("{:?}",grade_a);
    if (grade_a == grade_a1){
        println!("相等");
    }
    else{
        println!("不相等");
    }

    let fruit= food::水果("苹果","香蕉","梨子");
    println!("{:?}",fruit);
    print_first_fruit_member(fruit);
    let v = food::蔬菜(["白菜".to_string(),"萝卜".to_string(),"黄瓜".to_string(),"冬瓜".to_string(),"南瓜".to_string()]);
    println!("{:?}",v);
}

fn print_first_fruit_member<'a>(fruit: food<'a>) {
    if let food::水果(first, second, third) = fruit {
        println!("{},{},{}", first,second,third);
    } else {
        println!("The provided food is not a fruit.");
    }

}

上例中,food允许不同成员有不同的类型值。

 

二、特别的枚举-Option

按照作者的意思,Option<T>是一个很有用的枚
Option<T>{
 Some(T),
 None
}

特殊点在于:
1.定义于标准库中
2.它甚至被包含在了 prelude 之中,你不需要将其显式引入作用域
3.它的成员也是如此,可以不需要 Option:: 前缀来直接使用 Some 和 None


有用是怎么体现出来的?

1.首先Option具有许多方法,比如is_some()、is_none()、unwrap()等
2.Option<T>可以作为函数参数,比如fn some_function(option: Option<i32>)


以下是重点(基本上摘抄的):
那么当有一个 Option<T> 的值时,如何从 Some 成员中取出 T 的值来使用它呢?
Option<T> 枚举拥有大量用于各种情况的方法:
你可以查看它的文档。熟悉 Option<T> 的方法将对你的 Rust 之旅非常有用(原文)   示例
 fn main() {
    let some_number = Some(5); // some_number的类型是Option<i32>
    let some_string = Some("a string"); // some_string的类型是Option<&str>
    let absent_number: Option<i32> = None; // absent_number的类型是Option<i32>
    println!("some_number is {:?}", some_number);
    println!("some_string is {:?}", some_string);
    println!("absent_number is {:?}", absent_number);
    println!("absent_number is {:?}", absent_number.is_none());
    let name:String;
    name.push_str("abc");
 }

非常有用? 还没有体会出来,先记着! 

三、match和枚举

这里主要讨论如何匹配枚举的值,rust的解决方案是match。

1.match某种程度上可以看作rust中if-else的升级版,只不过match有时候可以让我们少打印一些代码而已
match不像java的switch那么傻瓜(传统),需要在每个分支上break,否则会继续执行下一个分支,虽然有那种情况存在,但是绝大部分时候,
我们并不需要break。
rust的match和新版本的java switch写法更加一致,已经不需要break了,且不会傻乎乎地每个匹配过去

2.顺便说一下,rust的创始人很喜欢下划线。所以下划分可以分割变量,也可以单独作为一个变量,但是不建议这么做
3.关于分支值的匹配
    a.rust的分支匹配是穷尽的,意思就是编译器如果发现你存在一些未匹配的分支,就会报错。  我们记住这个就可以了,因为编译器很贴心第处理了这个。
       这一点,的确比许多编译器好多了。
    b.rust可以使用多种方式匹配某个分支值,包括单个值、多个值、所有值
    c.rust使用下划线_来表示所有值,这样我们就可以直接使用这个变量了。这个倒是比许多语言的default稍微省事一些。这个并不是重点
    d._和other都可以表示所有值,能一起用,不会编译错误,但是固定有一个分支不可达到
     这意味着,rust的编译器目前虽然很贴心,但也不会浪费过多的时间去判断是否具有相同的分支--因为它允许有相同的分支,但是
     它的匹配机制使得只会有其中一个分支被执行,其它相同的并会被处理
    e.当某个分支值满足之后,匹配代码就结束了,不会像传统的java switch那么傻叉继续执行后面的。这个符合大部分人的思维

 

示例

/**
 * 年代枚举
 */
#[derive(Debug)] 
enum Age{Year1970,OtherYear}

/**
 * 硬币枚举
 */
enum Coin{一分(Age),二分,五分,一角,贰角,五角,一元}
/**
 * 文明枚举
 */
#[derive(Debug)] 
enum Civil{中国(Age),欧洲,美国,非洲}

fn main(){
    let coin = Coin::五分;
    let one =Coin::一元;
    match_branch_with_multiple_method(coin);
    match_branch_with_multiple_method(one);

    let civil = Civil::中国(Age::Year1970);
    let _ = Civil::欧洲;   //奇特的无意义的变量名称_,可以用,但是不建议。因为你无法直接传递,转赋也不方便,也不利于维护
    //let bad_=_;  //这样会报错
    //match_and_use_branch_value(_) //这样会报错
    let _欧洲 = Civil::欧洲;
    match_and_use_branch_value(civil);
    match_and_use_branch_value(_欧洲);
   
}

fn match_branch_with_multiple_method(coin:Coin){
    //演示如何匹配多值分支的方式:单个值、多个值、所有值
    match coin{
        Coin::一分(Age::Year1970) => println!("一分"),  //匹配分支特定值
        Coin::一分(_) => println!("一分"),   //匹配分支所有值
        Coin::一分(Age::OtherYear) |   Coin::一分(Age::Year1970)  => println!("一分"), //匹配分支多个值
        Coin::二分 => println!("二分"),
        Coin::五分 => println!("五分"),
        Coin::一角 => println!("一角"),
        Coin::五角 => println!("五角"),
        other => println!("一元 of other"),
        _=> println!("一元") 
    };
}

fn  match_and_use_branch_value(civil:Civil){
    //这种方式,可以利用类似匹配元组元素的方式,直接捕获分支值,并使用
    match civil {
        Civil::中国(age) => println!("有小聪明的中国:{:?},偶尔有一些亮色能拯救他们",age),  //自动从civil中捕获age值
        Civil::欧洲 => println!("肮胀但又聪明的欧洲"),
        _ => println!("{:?}",civil)   //如果把这个匹配去掉,那么会引发编译错误: patterns `Civil::美国` and `Civil::非洲` not covered
    };
}

 

如上例,match对枚举的匹配是穷尽的,这意味着一个值没有匹配,编译器就报错,这对于工程师倒是挺友好的!

 

四、语法糖if let

示例

#[derive(Debug)] 
enum Age{Year1970,OtherYear}

/**
 * 硬币枚举
 */
enum Coin{一分(Age),二分,五分,一角,贰角,五角,一元}

fn main(){
    let coin = Coin::一分(Age::Year1970);
    match coin{
        Coin::一分(Age::Year1970) => println!("70特有硬币?"),
        _=>println!("不是一分硬币")
    }

    //rust 的语法糖
    if let Coin::一分(Age::Year1970) = coin{
        println!("70特有硬币?");
    }else{  
        println!("不是一分硬币");
    }
    
    //不带 else的if let
    if let Coin::一分(Age::OtherYear)=coin{
        println!("不是70特有硬币");
    }

}

 

语法糖这个东西没有什么可说的,就是图方便而已。

如果没有ide和代码助手,那么的确还是不错的! 但你如果有ide和代码助手,那么这些语法糖的主要作用就是困扰。

五、小结

总而言之,rust的枚举和大部分语言看起来并没有什么本质的上的区别,但的确又有一些区别。

rust发明人的宗旨:让语言尽量用起来方便一些。 看起来好像得到了体现。   就我个人而言,不是太苟同!

rust的编译器的大作用,在这里有了体现!

标签:学习,枚举,let,rust,println,Coin,match
From: https://www.cnblogs.com/lzfhope/p/18535575

相关文章

  • (水下)目标检测/深度学习/计算机视觉国内外知名课题组
    大方向:目标检测、深度学习、计算机视觉国内课题组:1、港中文MMdetection课题组-号称计算机视觉界的黄埔军校香港中文大学的MMDetection课题组是隶属于香港中文大学多媒体实验室(multimedialaboratory,theChineseUniversityofHongKong)的一个重要研究团队。该多媒体实验......
  • 集成学习(Ensemble Learning)简介
    1集成学习作用俗话说:“三个臭皮匠赛过诸葛亮”。当使用某一种分类器不能使我们达到很好的效果的时候,我们不妨设想将这些分类效果不好的分类器组合一下,再去看看效果是否有提升,这就是集成学习(EnsembleLearning)的思想。集成学习是机器学习中的一种思想,它通过多个模型的组合......
  • 数字后端零基础入门系列 | Innovus零基础LAB学习Day10
    ###LAB19Innovus在线DRC检查这个章节的学习目标是学会使用数字IC后端设计实现PR工具innovus来检查drc。数字后端零基础入门系列|Innovus零基础LAB学习Day9数字后端零基础入门系列|Innovus零基础LAB学习Day8数字后端零基础入门系列|Innovus零基础LAB学习Day7首先......
  • markdown学习
    一级标题ctrl+1文章地址:https://blog.csdn.net/qq_41261251/article/details/102817673二级标题+2最多六级斜体用两个*扩起,或者ctrl+i加粗用两个**括起,或者ctrl+b粗斜体用***括起,或者ctrl+b+i哈哈哈分割线三个-或*或+删除线用~~括起,或者alt+shift+5下划线ctrl+u第一......
  • Python 学习记录 (4)
    Plotly常见可视化方案:以鸢尾花数据为例简单介绍:Ploty库也有大量统计可视化方案,并且这些可视化方案具有交互化属性。主要对鸢尾花数据进行处理与可视化。所展示的结果为交互界面的截图情况,这里不能进行交互。使用Plotly绘制散点图与箱型图,分类展示“花萼宽度”说明:类似'......
  • 荣登Nature! 持续学习(Continue Learning)取得最新突破
    2024深度学习发论文&模型涨点之——持续学习Nature发了一篇《Lossofplastisityindeepcontinuallearning》文章介绍了一种创新的算法——持续反向传播(ContinualBackpropagation),该算法通过在每次迭代中随机重置一小部分较少使用的神经元来保持网络的塑性。这种方法通过......
  • 学习方法1
    看到马斯克的采访有感,突然感觉其实从小到大的教育方法在工作中的学习成长依然有效,于是记录下针对一些还没有入门的技术,比如我现在想要去学习做一门微信小程序的游戏,路径如下:了解问题为什么想要做微信小程序游戏,原因是什么?微信小程序游戏有那些分类,他们的区别是什么,对于实现......
  • [豪の学习笔记] CI/CD相关 - Docker
    一、docker常见命令单独下载镜像文件dockerpull查看本地镜像文件dockerimages删除本地镜像文件dockerrmi基于dockerfile构建自定义镜像dockerbuild将打包好的镜像保存在本地dockersave加载外部镜像文件dockerload将本地镜像推送到镜像仓库dockerpush创建并......
  • Spring学习笔记_30——事务接口PlatformTransactionManager
    PlatformTransactionManager是Spring框架中事务管理的核心接口,它负责管理事务的创建、提交和回滚等操作。源码/**Copyright2002-2020theoriginalauthororauthors.**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethis......
  • 算法学习—归并排序
    1.算法介绍 归并算法是一种由冯·诺伊曼发明的分治算法,相较于普通排序算法时间复杂度较低,运行效率高。通常情况下,归并算法的时间复杂度为O(nlogn)。2.算法思想以及大致步骤 归并算法主要运用到了分治以及归并的思想,主要步骤如下:首先将一个无序数组分为n个有序的单个数......