最常见的逻辑控制流比如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的更多相关文章

  1. 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?

    我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...

  2. Codeforces 1197 E (dp+sort+二分) (Rust)

    原题链接 2300分 大意 俄罗斯套娃,每个有内容半径in和外围半径out in_i<out_i 如果 in_i >= out_j ,那么j可以放在i内 定义残留空间 = 一列嵌套的套娃 ...

  3. Rust的力量

    大约3年前,学习了一个星期的Go语言,然后就没有然后了. Go里面的有些东西设计很新颖,但是缺点也很明显. 上个周末,看了2个小时的Rust,我觉得Rust完全完胜Go语言. 再看Rust的定位,可以 ...

  4. 【转】对 Rust 语言的分析

    对 Rust 语言的分析 Rust 是一门最近比较热的语言,有很多人问过我对 Rust 的看法.由于我本人是一个语言专家,实现过几乎所有的语言特性,所以我不认为任何一种语言是新的.任何“新语言”对我来 ...

  5. Rust学习资源和路线

    Rust学习资源和路线 来源 https://rust-lang-cn.org/article/23 学习资源 The Rust Programming Language 堪称Rust的"T ...

  6. Rust到底值不值得学--Rust对比、特色和理念

    前言 其实我一直弄不明白一点,那就是计算机技术的发展,是让这个世界变得简单了,还是变得更复杂了. 当然这只是一个玩笑,可别把这个问题当真. 然而对于IT从业者来说,这可不是一个玩笑.几乎每一次的技术发 ...

  7. Rust 入门 (三)_上

    这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.本文我们介绍前两个内容,下一篇文章介绍后三个内容. 变量 默认情况下,rust 语言中声明的变量是不可变的,比 ...

  8. rust 网上资料记录(自用)

    最近要学嵌入式的rust,记录一些资料的url,方便自己查阅 书籍 常用的: rust圣经(不是权威指南那本)https://course.rs/ 中文 rust 参考手册 https://rustw ...

  9. nginx 之 grok 过滤

    简介   前面我们的nginx日志编码使用的json,logstash直接输入预定义好的 JSON 数据,这样就可以省略掉 filter/grok 配置,但是在我们的生产环境中,日志格式往往使用的是普 ...

  10. Golang全接触

    满打满算, 从好友推荐Golang至发文时, 使用Golang已经有1年多了. 这种时间对于C/C++ Java这些老者来说, 简直是菜鸟级别的经验 但作为新生代语言的特点就是实战. Golang这一 ...

随机推荐

  1. Spring Boot通过企业邮箱发邮件被Gmail退回的问题解决方法

    这两天给我们开发的Chrome插件:Youtube中文配音增加了账户注册和登录功能,其中有一步是邮箱验证,所以这边会在Spring Boot后台给用户的邮箱发个验证信息.如果发邮件,之前的文章教程里就 ...

  2. 聊一聊使用Spring事物时不生效的场景

    前言 今天介绍一下Spring事物不生效的场景,事物是我们在项目中经常使用的,如果是Java的话,基本上都使用Spring的事物,不过Spring的事物如果使用不当,那么就会导致事物失效或者不回滚,最 ...

  3. 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(4) -- 实现DataGrid数据的导入和导出操作

    在我们设计软件的很多地方,都看到需要对表格数据进行导入和导出的操作,主要是方便客户进行快速的数据处理和分享的功能,本篇随笔介绍基于WPF实现DataGrid数据的导入和导出操作. 1.系统界面设计 在 ...

  4. skynet的timer似乎有问题

    skynet.timeout 传进去 number 范围内的数值但是会溢出, 调查发现 skynet.timeout 调用的是 c 的方法: c.intcommand("TIMEOUT&qu ...

  5. Skynet通讯遇到的奇怪问题

    问题 最近在做一个内部通讯的服务器, 用的自带的gateserver和socketchannel做通讯, 在使用skynet.unpack或者string.unpack("XXXX" ...

  6. Go流程控制与快乐路径原则

    Go流程控制与快乐路径原则 目录 Go流程控制与快乐路径原则 一.流程控制基本介绍 二.if 语句 2.1 if 语句介绍 2.2 单分支结构的 if 语句形式 2.3 Go 的 if 语句的特点 2 ...

  7. 你也许不再需要使用 CSS Media Queries(媒体查询)了

    你也许不再需要使用 CSS Media Queries(媒体查询)了 最近,CSS 引入了一项新功能:Container Queries.它可以替代 Media Queries 并实现 Media Q ...

  8. Vue之事件冒泡

    1. 原生事件冒泡 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  9. P1182 数列分段 Section II 题解

    Problem 考察知识点:二分.贪心. 题目描述 对于给定的一个数组,现要将其分成 \(M\) 段,并要求每段连续,且每段和的最大值最小. 思路 二分答案出每段和最大值的最小值,然后贪心检验是否满足 ...

  10. http1.x,http2.0,https分别介绍以及他们的区别

    一.HTTP/1.x Http1.x 缺陷:线程阻塞,在同一时间,同一域名的请求有一定数量限制,超过限制数目的请求会被阻塞 http1.0 缺陷:浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要 ...