通过match看rust
最常见的逻辑控制流比如if-else,switch,while等常用编程语言都支持,但恰巧rust语法中没有switch,取而代之的是更加强大适用的match匹配,我们就来看看rust的match有何奇特之处。
一、介绍
先来看一个简单的rust的match用法
enum Role{
Admin,
User,
Guest,
Unkown
} fn main(){
let role=Role::Admin;
match role{
Role::Admin=>println!("you're an admin."),
Role::User=>println!("you're a user."),
Role::Guest=>println!("you're a guest."),
_=>println!("deny to access.")
}
}
从这个例子可以看出,rust的match跟其它常用语言的switch功能相似。都是根据条件匹配分支。
比如C#实现:
enum
{
Admin,
User,
Guest,
Unkown
} void Main(){
var role=Role.Admin;
switch(role)
{
case Role.Admin:{Console.WriteLine("you're an admin."); break;}
case Role.User:{Console.WriteLine("you're an user."); break;}
case Role.Guest:{Console.WriteLine("you're an guest."); break;}
default:{Console.WriteLine("deny to access."); break;}
}
}
当然rust的match肯定不止于此,我们接着来看。
二、match配合变体enum解构
rust的变体enum可以包含不同数据类型,再加上match匹配可以轻松实现复杂的逻辑需求。
我们还是来看个例子,比如:
enum Operator{
Plus(i32,i32),
Subtract(i32,i32),
Multiply(i32,i32),
Divide(i32,i32),
Log10(i32)
} fn main(){
let op=Operator::Plus(100,200);
match op{
Operator::Plus(a,b)=>println!("{a}+{b}={}",a+b),
Operator::Subtract(a,b)=>println!("{a}-{b}={}",a-b),
Operator::Multiply(a,b)=>println!("{a}x{b}={}",a*b),
Operator::Divide(a,b)=>println!("{a}/{b}={}",a/b),
Operator::Log10(a)=>println!("log10({a})={}",a.ilog10()),
}
}
类似这样的需求还是比较多的,比如处理鼠标事件
enum MouseEvent{
MoveIn,
MoveOut,
Click(x,y),
...
}
像这个例子在面向对象的编程语言中,肯定是使用类型继承实现来到达目的,继承并非不好,而是组合才是更佳思维方式,就好比社会各种组织都是靠协作,而非强行大一统,每个部分都有自身最高效的运作方式,强行一致这样的组织也效率低下。
三、复杂match匹配臂
1、匹配区间模式
fn main() {
let num=100;
match num{
x @ 1 ..=3| x @ 6 ..=9=>println!("case 1.{x}"),
4|5=>println!("case 2.b"),
x=>println!("case 3.{x}")
}
}
2、匹配通配符模式
fn main(){
let test=vec!["b", "m", "r","x","n","t","f","j"];
let s=(2,3,&test[0..3]);
match s{
(_,3,[..,"j"])=>println!("case 1."),
(2,_,["rust",end @ ..])=>println!("case 2.{:?}",end),
(_,_,_)=>println!("case 3."),
}
}
当然还有一些其它的模式匹配就不一一说明了。
四、用match消除if-else
if-else是所有编程语言中最简单直接的逻辑流控制方式,以至于被滥用了,在加上变量命名随意,词不达意使得代码难以理解(最近自嘲的”防御式编程“例外),说实话三层if-else就足以让人琢磨,我曾见到过十几层的if-else,一个方法上千行,再后来曾几何时编程流行消除if-else,以C++,Java,C#等流行面向对象语言大多使用设计模式来消除if-else,以至于设计模式被滥用了。
if-else并非是恶,既然提供了当用则用,无需顾虑太多。
在rust中对于单个Option<T>还是推荐用if let方式处理比较简单,比如:
[Debug]
struct User{
user_name:String,
age:u8
}
fn get_user(user_name:&str,pwd:&str)->Option<User>{
if user_name=="admin" && pwd=="123456"{
Some(User{user_name,age:20})
} else{
None
}
} fn main(){
let user=get_user("admin","123456");
if let Some(user)=user{
println!("login success {:?}",user);
}
}
我们应该谨防的是一个函数大段代码多层if-else嵌套,这个就是坏味道了。在其它常用编程语言中可能我们会用if-else写出这样的代码,伪代码比如:
if user.phone!=null{
if user.email!=null{
send_message(user.phone);
send_email(user.email);
log("优质客户");
}else{
send_message(user.phone);
log("普通客户");
}
}else{
if user.email!=null{
send_email(user.email);
log("一般客户");
}else{
log("待发展客户");
}
}
if-else是不是看得眼都花了,如果逻辑再复杂一些,这样的if-else嵌套更多层,人都麻了,不上个设计模式都有点不好意思了。
我们来用rust的mach匹配看看如何消除使得代码更加清晰直观。伪代码如下:
struct User{
phone:Option<String>,
email:Option<String>
} fn main(){
let user=User{phone:None,email:"bm@vv.com".to_owned()}; match(user.phone,user.email){
(Some(phone),Some(emial))=>{
send_message(user.phone);
send_email(user.email);
log("优质客户");
},
(Some(phone),None)=>{
send_message(user.phone);
log("普通客户");
},
(None,Some(email))=>{
send_email(user.email);
log("一般客户");
},
(_,_)=>log("待发展客户")
}
}
rust的match可以匹配多个目标,match使得层级单一了,整体逻辑是不是清晰多了。
好了,啰嗦了这么多,感谢各位看官驻足在此停留。
文章在博客园、微信公众号等平台发布,转载请注明来源(bmrxntfj)
通过match看rust的更多相关文章
- 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?
我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...
- Codeforces 1197 E (dp+sort+二分) (Rust)
原题链接 2300分 大意 俄罗斯套娃,每个有内容半径in和外围半径out in_i<out_i 如果 in_i >= out_j ,那么j可以放在i内 定义残留空间 = 一列嵌套的套娃 ...
- Rust的力量
大约3年前,学习了一个星期的Go语言,然后就没有然后了. Go里面的有些东西设计很新颖,但是缺点也很明显. 上个周末,看了2个小时的Rust,我觉得Rust完全完胜Go语言. 再看Rust的定位,可以 ...
- 【转】对 Rust 语言的分析
对 Rust 语言的分析 Rust 是一门最近比较热的语言,有很多人问过我对 Rust 的看法.由于我本人是一个语言专家,实现过几乎所有的语言特性,所以我不认为任何一种语言是新的.任何“新语言”对我来 ...
- Rust学习资源和路线
Rust学习资源和路线 来源 https://rust-lang-cn.org/article/23 学习资源 The Rust Programming Language 堪称Rust的"T ...
- Rust到底值不值得学--Rust对比、特色和理念
前言 其实我一直弄不明白一点,那就是计算机技术的发展,是让这个世界变得简单了,还是变得更复杂了. 当然这只是一个玩笑,可别把这个问题当真. 然而对于IT从业者来说,这可不是一个玩笑.几乎每一次的技术发 ...
- Rust 入门 (三)_上
这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.本文我们介绍前两个内容,下一篇文章介绍后三个内容. 变量 默认情况下,rust 语言中声明的变量是不可变的,比 ...
- rust 网上资料记录(自用)
最近要学嵌入式的rust,记录一些资料的url,方便自己查阅 书籍 常用的: rust圣经(不是权威指南那本)https://course.rs/ 中文 rust 参考手册 https://rustw ...
- nginx 之 grok 过滤
简介 前面我们的nginx日志编码使用的json,logstash直接输入预定义好的 JSON 数据,这样就可以省略掉 filter/grok 配置,但是在我们的生产环境中,日志格式往往使用的是普 ...
- Golang全接触
满打满算, 从好友推荐Golang至发文时, 使用Golang已经有1年多了. 这种时间对于C/C++ Java这些老者来说, 简直是菜鸟级别的经验 但作为新生代语言的特点就是实战. Golang这一 ...
随机推荐
- ios添加库文件
- 利用RATF框架实现web状态的监控
之前,我们已经说明了如何实现一个我们的接口测试框架RATF,当然这个框架不止可以用于管理我们的接口测试代码,我们还可以用他来对我们的web进行简单粗暴的监控. 原理: 1. 通过使用配置文件,对要监控 ...
- 弹性数据库连接池探活策略调研(一)——HikariCP
调研背景: 数据库连接建立是比较昂贵的操作(至少对于 OLTP),不仅要建立 TCP 连接外还需要进行连接鉴权操作,所以客户端通常会把数据库连接保存到连接池中进行复用.连接池维护到弹性数据库(JED) ...
- HDLbits_Conwaylife
题目介绍 题目链接 Conwaylife 简介 题目要求我们实现一个康威生命游戏的电路. 该游戏在一个二维网格空间中进行,在该题目中是 16 * 16 的大小,每一个格子都有两种状态(0 或 1),代 ...
- 一文搞懂 OTP 双因素认证
GitHub 在 2023 年 3 月推出了双因素认证(two-factor authentication)简称 2FA,并且承诺所有在 GitHub 上贡献的开发者在 2023 年底前启用双因素认证 ...
- jmeter不用工具获取随机值的几种方法
第一种:直接获取 "vcContent": "${__time(yyyyMMddHHmmss)}${__RandomString(8,QWERTYUIOPASDFGHJK ...
- ChatGPT 是如何产生心智的?
一.前言 - ChatGPT真的产生心智了吗? 来自斯坦福大学的最新研究结论,一经发出就造成了学术圈的轰动,"原本认为是人类独有的心智理论(Theory of Mind,ToM),已经出现在 ...
- [GXYCTF 2019]Ping Ping Ping
题目就是ping,而且这还有一个查询窗口,就随便查询试试 ping了一下本地,发现没有什么很大的作用,给出了提示是php可以执行系统函数这就感到神奇了,就还是上网搜了搜 发现可以在查询IP后面进行拼接 ...
- Qt信号槽与事件循环学习笔记
事件与事件循环 信号槽机制 事件与事件循环 在Qt中,事件(event)被封装为QEvent类/子类对象,用来表示应用内部或外部发生的各种事情.事件可以被任何QObject子类的对象接收并处理. 根据 ...
- redis主从同步及redis哨兵机制
1.主从和哨兵的作用: 角色 作用 主从 1.(提供)数据副本:多一份数据副本,保证redis高可用 2. 扩展(读)性能:如容量.QPS等 哨兵 1.监控: 监控redis主库及从库运行状态: 2 ...