• Rust中的模式匹配


    一、let模式匹配

    在其它一些语言中,let x = 5 之类的语句,仅仅只是赋值语句。但是在rust中,可以换个角度理解,认为5这个值匹配到了x变量。如果觉得有些牵强,可以再来一个示例:

        let (a,b)=(1,3);
        println!("{},{}",a,b);
    

    上面的示例,表示(1,3)这个元组,匹配(a,b)这一组变量,即a=1, b=3,类似的,struct也可以这样匹配:

    struct Point {
        x: i32,
        y: i32,
    }
    
    fn main() {
        let p = Point { x: 10, y: 20 };
        //模式匹配
        let Point { x, y } = p;
        //x=10,y=20
        println!("x:{},y:{}", x, y);
    }
    

      

    二、match匹配

    2.1 匹配简单类型

        let x = 1;
        match x {
            1 => println!("x=1"),
            2 => println!("x=2"),
            //"_"相当于java中switch的default
            _ => println!("default"),
        }
    
        let y = 2;
        match y {
            //匹配1或2
            1 | 2 => println!("y=1 or 2"),
            _ => println!("default"),
        }
    
        let z = 1;
        match z {
            //匹配1到5
            1..=5 => println!("z between 1 and 5"),
            _ => println!("default"),
        }
    
        let c = 'z';
        match c {
            //匹配a到z
            'a'..='z' => println!("{} in [a-z]", c),
            _ => println!("other"),
        }
    

    2.2 匹配枚举

    以最常用的Option enum为例:

        let x = Some(2);
        let x_result = match x {
            //精确匹配Some(5),x=Some(2),会匹配失败
            Some(5) => 5,
            _ => -1,
        };
        println!("{}",x_result);
    
        let x = Some(2);
        let x_result = match x {
            //只要x有值,就能匹配成功
            Some(n) => n,
            _ => -1,
        };
        println!("{}",x_result);
    
        let x = Some(3);
        let x_result = match x {
            //匹配时,还能指定条件,3>1,下面这行会匹配成功
            Some(n) if n>1 => n,
            _ => -1,
        };
        println!("{}",x_result);
    

    输出:

    -1
    2
    3

    另外,有些情况下,match还可以用if let语法糖简化代码:

        if let Some(v) = Some(5) {
            println!("{}", v);
        };
    
        //上面的代码,等效于下面这几行:
        let w = Some(5);
        match w {
            Some(n) => {
                println!("{}", n)
            }
            _ => {}
        }
    

    有时候,只需要匹配enum类型,不关注值,可以用_来忽略值

        let x = Some(4);
        let y = Some(5);
        match(x,y){
            (Some(_),Some(_)) => println!("both are Some Type"),
            _ => println!("others")
        }
    

    关于“_”,还有一些小技巧,如果只声明1个变量,不使用,rust编译器会警告:

    上图的提示,已经给出建议,可以加_,即改成let _x=10,就不会报警了。

    另外_在模式匹配中,还可以避免所有权转移:

        let s = Some(String::from("hello"));
        //由于_不关注值,所以s的所有权不会move到_
        if let Some(_) = s{
            println!("found a string");
        }
        //这里能正常输出
        println!("s:{:?}",s);
    

    但如果,把Some(_),换成其它方式,比如

    不仅仅是系统自带的enum,开发人员自定义的enum也一样可以进行匹配:

        enum Order {
            New { order_id: i32 },
        }
    
        let o1 = Order::New { order_id: 1 };
    
        match o1 {
            Order::New { order_id: x } if x >= 0 && x <= 10 => {
                println!("order_id:{} between 0 and 10", x)
            }
            _ => {}
        }
    
        //与上面的写法等效(注意多了1个@符号,表示把匹配到的值,赋值到@修饰的变量n里)
        match o1 {
            Order::New {
                order_id: n @ 1..=10,
            } => println!("order_id:{} between 0 and 10", n),
            _ => {}
        }
    

    2.3 匹配元组

        let t = (1, 2,3);
        match t {
            //仅匹配第1项,其它元素忽略
            (1, ..) => println!("first item is 1"),
            _ => println!("default"),
        }
    
        let t = (2, 3);
        match t {
            //匹配第1项,第2项放到变量n里
            (1, n) => println!("{},{}", 1, n),
            _ => println!("default"),
        }
    
        let t = (1, 2, 3, 4, 5, 6);
        match t {
            //匹配第1项与最后1项
            (1, .., 6) => println!("first:1,last:6"),
            _ => println!("others"),
        }
    

    2.4 匹配struct

        struct Point {
            x: i32,
            y: i32,
        }
    
        let p = Point { x: 10, y: 20 };
        match p {
            Point { x: 10, y: 20 } => println!("完全匹配!"),
            Point { x: 5, y } => println!("要求x匹配5,y无所谓"),
            Point { x, y } => println!("p中的x,y匹配到{},{}", x, y),
            _ => println!("others"),
        }
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    软件开发规范
    Fail2ban + firewalld 防护doss攻击
    SourceTree&Git部分名词解释
    训子
    一个网络下,手机如何访问本地网址
    tempalte.js的一般用法
    template.js的介绍
    获取URL中的参数
    js判断苹果和安卓端或者wp端
    HTML5与WebGL编程
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/15614552.html
Copyright © 2020-2023  润新知