2.8 rust 枚举与模式匹配
Enums and Pattern Matching
摘要
枚举定义
enum IpAddrKind {
V4,
V6,
}
枚举方法
fn main() {
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {
// method body would be defined here
}
}
let m = Message::Write(String::from("hello"));
m.call();
}
Option<T>使用
match使用
Defining an Enum
枚举属性的类型统一为枚举的名称
enum IpAddrKind {
V4,
V6,
}
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
Note that the variants of the enum are namespaced under its identifier, and we use a double colon to separate the two. The reason this is useful is that now both values IpAddrKind::V4 and IpAddrKind::V6 are of the same type: IpAddrKind. We can then, for instance, define a function that takes any IpAddrKind:
fn route(ip_kind: IpAddrKind) {}
route(IpAddrKind::V4);
route(IpAddrKind::V6);
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"));
fn main() {
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
}
#![allow(unused_variables)]
fn main() {
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),
}
This enum has four variants with different types:
Quithas no data associated with it at all.Moveincludes an anonymous struct inside it.Writeincludes a singleString.ChangeColorincludes threei32values.
fn main() {
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {
// method body would be defined here
}
}
let m = Message::Write(String::from("hello"));
m.call();
}
[derive(Debug)] 会自动实现一个输出格式,然后就可以使用{:?}输出枚举
fn testEnum(){
#[derive(Debug)]
enum Message {
Quit,
Move{x: i16, y: i16},
Write(String),
ChangeColor(i32,i32,i32),
}
impl Message {
fn call(&self) {
let v1 = Message::Quit;
let v2 = Message::Move{x: 25, y: 25};
let v4 = Message::ChangeColor(100,100,100);
println!("{:#?} ",v1);
println!("{:#?} ",v2);
println!("{:?}",v4);
}
}
let m = Message::Write(String::from("enum show "));
println!("{:?}",m);
m.call();
}
Write("enum show ")
Quit
Move {
x: 25,
y: 25,
}
ChangeColor(100, 100, 100)
Rust枚举中一个超级重要的的特性:所有枚举都是同一类型,这一点在rust中的应用, 相当于Java的抽象、继承,相当于C++中的泛型,针对此特点,特举例如下
#[derive(Debug)]
enum WorkSort {
Student,
Teacher,
Doctor,
} impl WorkSort{
pub fn desc(&self){
println!("I am a {:?}",self);
}
} pub fn test1(){
let tch = WorkSort::Teacher;
tch.desc(); let std = WorkSort::Student;
std.desc(); }
调用test1方法,输出
I am a Teacher
I am a Student
The Option Enum and Its Advantages Over Null Values
Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the null feature that many other languages have. Null is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null.
The problem isn’t really with the concept but with the particular implementation. As such, Rust does not have nulls, but it does have an enum that can encode the concept of a value being present or absent. This enum is Option<T>, and it is defined by the standard library as follows:
#![allow(unused_variables)]
fn main() {
enum Option<T> {
Some(T),
None,
}
}
The Option<T> enum is so useful that it’s even included in the prelude; you don’t need to bring it into scope explicitly. In addition, so are its variants: you can use Some and None directly without the Option:: prefix. The Option<T> enum is still just a regular enum, and Some(T) and None are still variants of type Option<T>.
For now, all you need to know is that <T> means the Some variant of the Option enum can hold one piece of data of any type. Here are some examples of using Option values to hold number types and string types:
fn main() {
let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;
}
In short, because Option<T> and T (where T can be any type) are different types, the compiler won’t let us use an Option<T> value as if it were definitely a valid value. For example, this code won’t compile because it’s trying to add an i8 to an Option<i8>:
fn main() {
let x: i8 = 5;
let y: Option<i8> = Some(5);
let sum = x + y;//error
}
The match Control Flow Operator
Rust has an extremely powerful control flow operator called match that allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things;
fn main() {
println!("----------match----------");
let coin = Coin::Penny;
let res = value_in_cents(coin);
println!("{}",res);
let coin = Coin::Dime;
let res = value_in_cents(coin);
println!("{}",res);
}
enum Coin {
Penny,
Nockel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nockel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
$ cargo run
Compiling enum_match v0.1.0 (/opt/wks/rust_study/enum_match)
warning: variant is never constructed: `Nockel`
--> src/main.rs:15:5
|
15 | Nockel,
| ^^^^^^
|
= note: `#[warn(dead_code)]` on by default warning: variant is never constructed: `Quarter`
--> src/main.rs:17:5
|
17 | Quarter,
| ^^^^^^^ warning: 2 warnings emitted Finished dev [unoptimized + debuginfo] target(s) in 0.52s
Running `target/debug/enum_match`
----------match----------
1
10
#[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
}
}
} fn main() {
value_in_cents(Coin::Quarter(UsState::Alaska));
}
Option<T> match
#[derive(Debug)]
enum Option<T> {
None,
Some(T)
} fn plus_one(x: Option<i32>) -> Option<i32>{
match x {
Option::None => Option::None,
Option::Some(i) => Option::Some(i+1),
}
} fn test_match(){
let five = Option::Some(5);
let six = plus_one(five);
println!("{:?}",six);
let none = plus_one(Option::None);
println!("{:?}",none);
}
Matches Are Exhaustive
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}
We didn’t handle the None case, so this code will cause a bug. Luckily, it’s a bug Rust knows how to catch. If we try to compile this code, we’ll get this error:
$ cargo run
Compiling enums v0.1.0 (file:///projects/enums)
error[E0004]: non-exhaustive patterns: `None` not covered
--> src/main.rs:3:15
|
3 | match x {
| ^ pattern `None` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error: aborting due to previous error For more information about this error, try `rustc --explain E0004`.
error: could not compile `enums`. To learn more, run the command again with --verbose.
The _ Placeholder
Rust also has a pattern we can use when we don’t want to list all possible values. For example, a u8 can have valid values of 0 through 255. If we only care about the values 1, 3, 5, and 7, we don’t want to have to list out 0, 2, 4, 6, 8, 9 all the way up to 255. Fortunately, we don’t have to: we can use the special pattern _ instead:
fn main() {
let some_u8_value = 0u8;
match some_u8_value {
1 => println!("one"),
3 => println!("three"),
5 => println!("five"),
7 => println!("seven"),
_ => (),
}
}
_ => (),
这一行表示轮空,什么也不会输出
The _ pattern will match any value. By putting it after our other arms, the _ will match all the possible cases that aren’t specified before it. The () is just the unit value, so nothing will happen in the _ case. As a result, we can say that we want to do nothing for all the possible values that we don’t list before the _ placeholder.
However, the match expression can be a bit wordy in a situation in which we care about only one of the cases. For this situation, Rust provides if let.
Concise Control flow with if let
#![allow(unused_variables)]
fn main() {
println!("Hello, match!");
let1();
let2();
} #[derive(Debug)]
enum Option<T> {
Some(T),
None
} fn let1(){
let some_u3_value = Option::Some(0u8);
match some_u3_value {
Option::Some(3) => println!("three"),
_ => (),
} if let Option::Some(3) = some_u3_value{
println!("three");
} } fn let2(){
let some_u3_value = Option::Some(0u8);
let mut count = 0;
match some_u3_value {
Option::Some(3) => println!("three"),
_ => count += 1,
} if let Option::Some(3) = some_u3_value{
println!("three");
}else{
count += 1;
}
println!("{}",count);
}
2.8 rust 枚举与模式匹配的更多相关文章
- Rust中的枚举及模式匹配
这个enum的用法,比c要强,和GO类似. enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> ...
- 学习Rust第一天 Rust语言特点
学习Rust之前,我觉得应该首先了解Rust语言的设计目的是什么?为什么会诞生这门语言?这门语言和其他的语言有什么不同. Rust语言的设计特点 高性能:rust拥有和C++相近的性能表现,所以在嵌入 ...
- Swift 模式匹配
前言 在 Swift 中模式匹配是个重要的概念. 最常用的模式匹配是 switch 语法. 模式匹配非常灵活,在使用 switch 进行一轮模式匹配时,不需要所有的 case 都是同一种风格. let ...
- swift 模式
原文:http://www.cocoachina.com/newbie/basic/2014/0612/8800.html 模式(pattern)代表了单个值或者复合值的结构.比如,元组(1, 2)的 ...
- ballerina 学习十五 控制流
ballerina 的控制流没有什么特殊,只是相比一般语言多了一个模式匹配的操作match ,实际上其他语言(erlang elixir rust 中的模式匹配是很强大的) 简单例子 if/else ...
- rust Option枚举
枚举 1 fn main() { 2 let a_binding; 3 { 4 let x = 2; 5 a_binding = x * x; 6 } 7 println!("a bindi ...
- 专访Rust——由Mozilla开发的系统编程语言(目标人群就是那些纠结的C++程序员,甚至也是他们自己)
Rust是由Mozilla开发的专门用来编写高性能应用程序的系统编程语言.以下是对Rust的创始人——Graydon Hoare的采访. Graydon Hoare,自称为职业编程语言工程师,从200 ...
- rust 高级话题
目录 rust高级话题 前言 零大小类型ZST 动态大小类型DST 正确的安装方法 结构体 复制和移动 特征对象 引用.生命周期.所有权 生命周期 错误处理 交叉编译 智能指针 闭包 动态分派和静态分 ...
- rust语法
目录 rust语法 前言 一.数据类型 1.1 标量scalar 1.2 复合compound 1.3 切片slice 1.4 引用(借用)reference 1.5 智能指针smart pointe ...
随机推荐
- k8s入坑之路(12)ingress-nginx安装配置四层代理
ingress官方文档地址:http://docs.kubernetes.org.cn/ https://feisky.gitbooks.io/kubernetes/content/plugins/ ...
- 2020 天翼杯 部分wp
天翼杯 呜呜呜呜 是我太菜了 Web APItest 源码 const express = require("express"); const cors = require(&qu ...
- c++学习笔记6(结构化程序设计的不足)
结构化程序设计 c语言使用结构化程序设计: 程序=数据结构+算法 程序有全局变量以及众多相互调用的函数组成 算法以函数的形式实现,用于对数据结构进行操作 结构化程序设计不足 软件业的目标是更快,更正确 ...
- 微信小程序(六)
MINA 框架: 启动: 冷启动,热启动 加载: 生命周期 路由: 事件: 事件时视图层到逻辑层的通信方式 事件可以将用户的行为反馈到逻辑层进行处理 事件可以绑定在组件上,触发事件后就会执行逻辑层对应 ...
- IDEA下载 使用快捷方式 以及一些小教程
IDEA下载 使用快捷方式 以及一些小教程 Idea下载 网址:链接: https://pan.baidu.com/s/1xRr3mhM6_VDHqC_w0F1MjQ 提取码: 6ypi 下载,安装方 ...
- 【JVM】JVM 概述、内存结构、溢出、调优(基础结构+StringTable+Unsafe+ByteBuffer)
什么是 JVM ? 定义 Java Virtual Machine - java 程序的运行环境(java 二进制字节码的运行环境) 好处 一次编写,到处运行 自动内存管理,垃圾回收功能 数组下标越界 ...
- 利用opencv进行简易的拍照并处理照片
今天用python写了一个调用摄像头拍照并对图片进行素描化或动漫化的小demo. 首先我的环境是:PyCharm+python3.8+opencv-python(4.4.0.42) 我们分析一下思路, ...
- [atAGC055B]ABC Supremacy
将第$i$个字符在$A->C->B->A$这个环上操作$i$次,而此时的操作也即将$AAA,BBB$或$CCC$变为其中的另一个字符串 通过操作$XXXY->YYYY-> ...
- [loj6031]字符串
为了方便,用$N=10^{5}$来描述复杂度 (对原串建立SAM)注意到$\sum|w|=qk\le N$,考虑对$q$和$k$的大小关系分类讨论: 1.若$q\le k$,即询问次数较少,将其与原串 ...
- 关于uni-app导航栏中 中间大图标的设置
在uni-app的开发过程中,想要将位于中间的图标设置更大,通过一般的更改导航栏图标大小方式实现不了.经过查看官方文档可以发现,我们可以通过midbutton来设置中间tabbar的样式. 但前提是, ...