首页 > 其他分享 >通过match看rust

通过match看rust

时间:2023-12-14 15:46:13浏览次数:18  
标签:通过 else rust println email match user

  

  最常见的逻辑控制流比如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:"[email protected]".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)

标签:通过,else,rust,println,email,match,user
From: https://www.cnblogs.com/bmrxntfj/p/rust_match.html

相关文章

  • Unity3D协议怎样通过应用层来实现可靠性
    Unity3D是一款流行的游戏开发引擎,它提供了丰富的网络功能来支持多人游戏。其中,UDP(UserDatagramProtocol)是一种无连接的传输协议,它提供了高效的数据传输,但不保证数据的可靠性。本文将介绍如何通过应用层来实现UDP协议的可靠性,并给出技术详解和代码实现。对啦!这里有个游戏开发交......
  • Arcgis中通过函数实现字符串截取
    效果从字符串中提取最右侧的符号,如“/”后面的字符串步骤1、VBdimbbindex=instrrev([WGCJ],"/")bb=right([WGCJ],len([WGCJ])-index)2、pythondefbb(aa):index=(aa.rfind("/"))bb=aa[index+1:]returnbb......
  • Unity3D UDP协议怎样通过应用层来实现可靠性
    Unity3D是一款流行的游戏开发引擎,它提供了丰富的网络功能来支持多人游戏。其中,UDP(UserDatagramProtocol)是一种无连接的传输协议,它提供了高效的数据传输,但不保证数据的可靠性。本文将介绍如何通过应用层来实现UDP协议的可靠性,并给出技术详解和代码实现。对啦!这里有个游戏开发交......
  • 通过屏幕输入一个长方形的长和宽,并求出该长方形的周长和面积。(并显示出来)
    #define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>voidprint(){ printf("*************计算方形的周长和面积***********\n"); printf("*******************************************\n"); printf("*************选择你想要进行的操作:>*********......
  • 通过Solopace.Gem 无需公网IP远程访问智能家庭(HomeAssistant)
    Solopace.Gem可以便捷地让你再任何地方访问家中的HomeAssistant,这为个人用户提供了更便利的控制家庭自动化设备的方式。以下是一份教程,展示如何通过Solopace.Gem访问HomeAssistant:---如何通过Solopace.Gem访问HomeAssistant步骤1:安装Solopace.Gem1.注册与安装:访问Solopace.Gem......
  • cbindgen rust 代码生成c binding 的工具
    rust与c以及c与rust的互调用还是比较常见的需求,很多时候自己写可能比较费事,但是使用一些工具就比较方便了cbindgen是一个对于rust代码生成cbinding的工具参考使用基于cbindgen将rust的代码生成对应的c头文件,之后基于cmake构建项目项目结构 ├──......
  • 通过正则表达式获取字符串中的省市区
    通过正则表达式获取字符串中的省市区//[^省]+省|.+自治区|[^澳门]+澳门|北京|重庆|上海|天津|台湾|[^香港]+香港|[^市]+市)越前面的优先级越高,会取优先级高的第一个匹配到的进行截取//^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+......
  • 通过脚本批量修改windows系统任务计划
    需求:修改已有的windows系统任务计划方法:一、通过python实现需要安装pywin32模块pipinstallpywin32查询任务计划importwin32com.clientTASK_ENUM_HIDDEN=1TASK_STATE={0:'Unknown',1:'Disabled',2:'Queued',3:......
  • 通过excel表格批量修改文件夹名称
    脚本功能这个脚本用于重命名文件夹,特别是在多层嵌套的文件夹结构中。它通过读取一个Excel表格来获取重命名的信息。表格的第一列应包含当前的文件夹名称,第二列包含您想要更改为的新名称。脚本会递归地遍历指定路径下的所有文件夹,并根据表格中的信息重命名匹配的文件夹。 impo......
  • 聊一聊Rust的enum
    enum在实际编程中是非常常用的,enum的目的就是为了清晰定义出散落在系统各个角落的相同概念的有限固定值。一、enum介绍如果是简单定义固定值,我们可以使用常量const。比如publicconstintMAX_THREAD_COUNT=100;在C语言中,我们可以这样定义一个枚举方便各处使用,比如:enumDi......