通过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这一 ...
随机推荐
- erlang和rabbitMq在ubuntu上的安装过程
安装rabbitMQ的前提是安装上erlang,所以从erlang安装开始. 安装erlang 1,先升级一下 $:sudo apt-get update 如果软件源有问题 修改etc/apt/sou ...
- 【Qt6】工具提示以及调色板设置
工具提示即 Tool Tip,当用户把鼠标移动到某个UI对象上并悬停片刻,就会出现一个"短小精悍"的窗口,显示一些说明性文本.一般就是功能描述,让用户知道这个XX是干啥用的. 在 ...
- 《SQL与数据库基础》13. 视图
目录 视图 简介 语法 检查选项 视图更新 视图作用 本文以 MySQL 为例 视图 简介 视图(View)是一种虚拟存在的表.视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的 ...
- 如何使用Grid中的repeat函数
在本文中,我们将探索 CSS Grid repeat() 函数的所有可能性,它允许我们高效地创建 Grid 列和行的模式,甚至无需媒体查询就可以创建响应式布局. 不要重复自己 通过 grid-temp ...
- 发布策略:蓝绿部署、金丝雀发布(灰度发布)、AB测试、滚动发布、红黑部署的概念与区别
蓝绿发布(Blue-Green Deployment) 蓝绿发布提供了一种零宕机的部署方式.不停老版本,部署新版本进行测试,确认OK,将流量切到新版本,然后老版本同时也升级到新版本.始终有两个版本同时 ...
- 创建Anaconda虚拟Python环境的方法
本文介绍在Anaconda环境下,创建.使用与删除Python虚拟环境的方法. 在Python的使用过程中,我们常常由于不同Python版本以及不同第三方库版本的支持情况与相互之间的冲突情况, ...
- 二叉搜索树(Binary Search Tree,BST)
二叉搜索树(Binary Search Tree,BST) 二叉搜索树(Binary Search Tree),也称二叉查找树或二叉排序树,是一种特殊的二叉树,它满足以下性质 对于二叉搜索树的每个节点 ...
- MySQL 分表查询
分表是一种数据库分割技术,用于将大表拆分成多个小表,以提高数据库的性能和可管理性.在MySQL中,可以使用多种方法进行分表,例如基于范围.哈希或列表等.下面将详细介绍MySQL如何分表以及分表后如何进 ...
- Journey -「CQOI 2021」
Day -1 Thu. & Fri. 恰逢学校运动会,于是向班主任申请了不去,然后就在机房坐着.不美好的事情可能就是文化课老师还留了这两天的作业,不过-> 一旦放弃了作业,什么都好说了呢 ...
- java实现 微信公众号推送消息 ,cv 就可运行!!!
一,注册公众号 1,官网地址:申请测试公众号 地址: 微信公众平台 (qq.com) 文档地址:微信开放文档 (qq.com) 2,注册后可以查看自己的appId 和 appsecret 3,创建模板 ...