经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Rust » 查看文章
通过match看rust
来源:cnblogs  作者:bmrxntfj  时间:2023/12/15 8:46:32  对本文有异议

  

  最常见的逻辑控制流比如if-else,switch,while等常用编程语言都支持,但恰巧rust语法中没有switch,取而代之的是更加强大适用的match匹配,我们就来看看rust的match有何奇特之处。


 一、介绍

先来看一个简单的rust的match用法

  1. enum Role{
  2. Admin,
  3. User,
  4. Guest,
  5. Unkown
  6. }
  7.  
  8. fn main(){
  9. let role=Role::Admin;
  10. match role{
  11. Role::Admin=>println!("you're an admin."),
  12. Role::User=>println!("you're a user."),
  13. Role::Guest=>println!("you're a guest."),
  14. _=>println!("deny to access.")
  15. }
  16. }

从这个例子可以看出,rust的match跟其它常用语言的switch功能相似。都是根据条件匹配分支。

比如C#实现:

  1. enum
  2. {
  3. Admin,
  4. User,
  5. Guest,
  6. Unkown
  7. }
  8.  
  9. void Main(){
  10. var role=Role.Admin;
  11. switch(role)
  12. {
  13. case Role.Admin:{Console.WriteLine("you're an admin."); break;}
  14. case Role.User:{Console.WriteLine("you're an user."); break;}
  15. case Role.Guest:{Console.WriteLine("you're an guest."); break;}
  16. default:{Console.WriteLine("deny to access."); break;}
  17. }
  18. }

当然rust的match肯定不止于此,我们接着来看。


 二、match配合变体enum解构

rust的变体enum可以包含不同数据类型,再加上match匹配可以轻松实现复杂的逻辑需求。
我们还是来看个例子,比如:

  1. enum Operator{
  2. Plus(i32,i32),
  3. Subtract(i32,i32),
  4. Multiply(i32,i32),
  5. Divide(i32,i32),
  6. Log10(i32)
  7. }
  8.  
  9. fn main(){
  10. let op=Operator::Plus(100,200);
  11. match op{
  12. Operator::Plus(a,b)=>println!("{a}+{b}={}",a+b),
  13. Operator::Subtract(a,b)=>println!("{a}-{b}={}",a-b),
  14. Operator::Multiply(a,b)=>println!("{a}x{b}={}",a*b),
  15. Operator::Divide(a,b)=>println!("{a}/{b}={}",a/b),
  16. Operator::Log10(a)=>println!("log10({a})={}",a.ilog10()),
  17. }
  18. }

类似这样的需求还是比较多的,比如处理鼠标事件

  1. enum MouseEvent{
  2. MoveIn,
  3. MoveOut,
  4. Click(x,y),
  5. ...
  6. }

像这个例子在面向对象的编程语言中,肯定是使用类型继承实现来到达目的,继承并非不好,而是组合才是更佳思维方式,就好比社会各种组织都是靠协作,而非强行大一统,每个部分都有自身最高效的运作方式,强行一致这样的组织也效率低下。


 三、复杂match匹配臂

1、匹配区间模式

  1. fn main() {
  2. let num=100;
  3. match num{
  4. x @ 1 ..=3| x @ 6 ..=9=>println!("case 1.{x}"),
  5. 4|5=>println!("case 2.b"),
  6. x=>println!("case 3.{x}")
  7. }
  8. }

  

2、匹配通配符模式

  1. fn main(){
  2. let test=vec!["b", "m", "r","x","n","t","f","j"];
  3. let s=(2,3,&test[0..3]);
  4. match s{
  5. (_,3,[..,"j"])=>println!("case 1."),
  6. (2,_,["rust",end @ ..])=>println!("case 2.{:?}",end),
  7. (_,_,_)=>println!("case 3."),
  8. }
  9. }

  

当然还有一些其它的模式匹配就不一一说明了。


 四、用match消除if-else

  if-else是所有编程语言中最简单直接的逻辑流控制方式,以至于被滥用了,在加上变量命名随意,词不达意使得代码难以理解(最近自嘲的”防御式编程“例外),说实话三层if-else就足以让人琢磨,我曾见到过十几层的if-else,一个方法上千行,再后来曾几何时编程流行消除if-else,以C++,Java,C#等流行面向对象语言大多使用设计模式来消除if-else,以至于设计模式被滥用了。

if-else并非是恶,既然提供了当用则用,无需顾虑太多。

在rust中对于单个Option<T>还是推荐用if let方式处理比较简单,比如:

  1. [Debug]
  2. struct User{
  3. user_name:String,
  4. age:u8
  5. }
  6. fn get_user(user_name:&str,pwd:&str)->Option<User>{
  7. if user_name=="admin" && pwd=="123456"{
  8. Some(User{user_name,age:20})
  9. } else{
  10. None
  11. }
  12. }
  13.  
  14. fn main(){
  15. let user=get_user("admin","123456");
  16. if let Some(user)=user{
  17. println!("login success {:?}",user);
  18. }
  19. }

  

我们应该谨防的是一个函数大段代码多层if-else嵌套,这个就是坏味道了。在其它常用编程语言中可能我们会用if-else写出这样的代码,伪代码比如:

  1. if user.phone!=null{
  2. if user.email!=null{
  3. send_message(user.phone);
  4. send_email(user.email);
  5. log("优质客户");
  6. }else{
  7. send_message(user.phone);
  8. log("普通客户");
  9. }
  10. }else{
  11. if user.email!=null{
  12. send_email(user.email);
  13. log("一般客户");
  14. }else{
  15. log("待发展客户");
  16. }
  17. }

  

if-else是不是看得眼都花了,如果逻辑再复杂一些,这样的if-else嵌套更多层,人都麻了,不上个设计模式都有点不好意思了。
我们来用rust的mach匹配看看如何消除使得代码更加清晰直观。伪代码如下:

  1. struct User{
  2. phone:Option<String>,
  3. email:Option<String>
  4. }
  5.  
  6. fn main(){
  7. let user=User{phone:None,email:"bm@vv.com".to_owned()};
  8. match(user.phone,user.email){
  9. (Some(phone),Some(emial))=>{
  10. send_message(user.phone);
  11. send_email(user.email);
  12. log("优质客户");
  13. },
  14. (Some(phone),None)=>{
  15. send_message(user.phone);
  16. log("普通客户");
  17. },
  18. (None,Some(email))=>{
  19. send_email(user.email);
  20. log("一般客户");
  21. },
  22. (_,_)=>log("待发展客户")
  23. }
  24. }

  

rust的match可以匹配多个目标,match使得层级单一了,整体逻辑是不是清晰多了。


 

好了,啰嗦了这么多,感谢各位看官驻足在此停留。

文章在博客园、微信公众号等平台发布,转载请注明来源(bmrxntfj)

原文链接:https://www.cnblogs.com/bmrxntfj/p/rust_match.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号