最常见的逻辑控制流比如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. 【实践篇】DDD脚手架及编码规范

    一.背景介绍 我们团队一直在持续推进业务系统的体系化治理工作,在这个过程中我们沉淀了自己的DDD脚手架项目.脚手架项目是体系化治理过程中比较重要的一环,它的作用有两点: (1)可以对新建的项目进行统一 ...

  2. 在 Android Studio Java 项目里混合 Kotlin 编程

    首先,先搞明白一个概念,这里的 Java 混合 Kotlin 是指文件层级的混合,即 Java 代码还是写在 .java 文件中,Kotlin 代码还是写在 .kt 文件中,只不过是可以在 Java ...

  3. Solution -「洛谷 P3600」随机数生成器

    Desciption Link. 给定一个值域在 \([1,x]\) 的长度为 \(n\) 的序列(由随机数构成),求给定一组区间中的最小值的最大值的期望. Solution 记: \[w=\max\ ...

  4. “&”控制命令的运行方式

    在Unix.Linux和类Unix系统中,& 符号有特定的意义,用于控制命令的运行方式.具体来说,& 在命令末尾使用时表示将该命令放入后台运行. 前台运行: 如果你在终端输入一个命令, ...

  5. 拟合优度R2较低怎么办

    拟合优度R2较低怎么办 (1)回归分为解释型回归和预测型回归. 预测型回归一般才会更看重2. 解释型回归更多的关注模型整体显著性以及自变量的统计显著性和经济意义显著 性即可. (2)可以对模型进行调整 ...

  6. Python socket实现简单聊天,同步输入和接收消息

    查的资料很多都是必须等待接收数据后才能再次输入.做了修改,使用多线程的形式,实现一边输入,一边接收 服务端代码 import socket import threading import sys im ...

  7. Python面向对象——1、什么是异常 2、为何处理异常 3、如何处理异常? 4、何时使用异常处理 网络编程的一些预备知识

    文章目录 异常 1.什么是异常 2.为何处理异常 3.如何处理异常? 4.何时使用异常处理 网络编程的一些预备知识 异常 1.什么是异常 异常是程序发生错误的信号.程序一旦出现错误,便会产生一个异常, ...

  8. 关于C++拷贝控制

    通常来说,对于类内动态分配资源的类需要进行拷贝控制:要在拷贝构造函数.拷贝赋值运算符.析构函数中实现安全高效的操作来管理内存.但是资源管理并不是一个类需要定义自己的拷贝控制成员的唯一原因.C++ Pr ...

  9. 一行代码搞定 font-size 响应式

    前言 公司要做大屏,但是大屏还要有个嵌在系统的版本,屏幕(iframe)小了但字体大了怎么办.网上找了很多代码都很长,个人参考了资料后实现了一个一行代码 font-size 响应式. TL;DR ht ...

  10. SQL-报错注入

    updatexml报错注入 updatexml (XML_document, XPath_string, new_value): 第一个参数:XML_document是String格式,为XML文档对 ...