• Rust Lang Book Ch.18 Patterns and Matching


    Rust中的Pattern能够包含以下内容:

    a) literal

    b)Destructured arrays, enums, structs, or tuples

    c) 变量

    d) 通配符

    e) placeholders

    以下的都算是pattern:

    a) match Arms

    b) if let

    c) while let

    d) for x in y 中的x

    e) let PATTERN = EXPRESSION

    f) function parameters, 例如&(x, y): &(i32, i32)

    Refutability

    能够match任何传过来的值的是irrefutable pattern。例如let x = 5中的x。

    与此对应的,有时可能match不了传过来的值的是refutable pattern,例如let Some(x) = some_option_value;

    一般来说,写程序时可以不重视pattern的Refutable和irrefutable之间的差别,但是,在弹出错误信息的时候要能够区别。P.S: Rust只允许match的最多一个arm是irrefutable match。

    Pattern Syntax

    1. 和固定值(literal)做对比

        let x = 1;
    
        match x {
            1 => println!("one"),
            2 => println!("two"),
            3 => println!("three"),
            _ => println!("anything"),
        }
    

      

    2. Named Variable

    let y = 5中的y是一个named variable也是一个irrefutable pattern。

    但是named variable也可能只是pattern的一部分。

        let x = Some(5);
        let y = 10;
    
        match x {
            Some(50) => println!("Got 50"),
            Some(y) => println!("Matched, y = {:?}", y),
            _ => println!("Default case, x = {:?}", x),
        }
    
        println!("at the end: x = {:?}, y = {:?}", x, y);
    //Output:
    //Matched, y = 5
    //注意在这里match内是一个新的作用域了,里面的Some(y)里面的y是个named variable,与外层的y=10无关

      

    Multiple Patterns

    可以用|把多个pattern连起来。

        let x = 1;
    
        match x {
            1 | 2 => println!("one or two"),
            3 => println!("three"),
            _ => println!("anything"),
        }
    

      

    Matching Ranges

    使用..=可以一次性匹配一个全闭区间。..=只能和数字或者char搭配使用。

        let x = 5;
    
        match x {
            1..=5 => println!("one through five"),
            _ => println!("something else"),
        }
    

      

        let x = 'c';
    
        match x {
            'a'..='j' => println!("early ASCII letter"),
            'k'..='z' => println!("late ASCII letter"),
            _ => println!("something else"),
        }

    Destructuring

    Destructuring Structs

    可以带域名,直接按顺序取named variable,也可以在给一部分域名中嵌套其他pattern

    struct Point {
        x: i32,
        y: i32,
    }
    
    fn main() {
        let p = Point { x: 0, y: 7 };
    
        let Point { x: a, y: b } = p;
        assert_eq!(0, a);
        assert_eq!(7, b);
    let Point {x, y} = p;
    assert_eq!(0, x); }

      

    fn main() {
        let p = Point { x: 0, y: 7 };
    
        match p {
            Point { x, y: 0 } => println!("On the x axis at {}", x),
            Point { x: 0, y } => println!("On the y axis at {}", y),
            Point { x, y } => println!("On neither axis: ({}, {})", x, y),
        }
    }
    

      

    Destructuring Enums

    enum Message {
        Quit,
        Move { x: i32, y: i32 },
        Write(String),
        ChangeColor(i32, i32, i32),
    }
    
    fn main() {
        let msg = Message::ChangeColor(0, 160, 255);
    
        match msg {
            Message::Quit => {
                println!("The Quit variant has no data to destructure.")
            }
            Message::Move { x, y } => {
                println!(
                    "Move in the x direction {} and in the y direction {}",
                    x, y
                );
            }
            Message::Write(text) => println!("Text message: {}", text),
            Message::ChangeColor(r, g, b) => println!(
                "Change the color to red {}, green {}, and blue {}",
                r, g, b
            ),
        }
    }
    

      

    Destructuring Nested Structs and Enums

    enum Color {
        Rgb(i32, i32, i32),
        Hsv(i32, i32, i32),
    }
    
    enum Message {
        Quit,
        Move { x: i32, y: i32 },
        Write(String),
        ChangeColor(Color),
    }
    
    fn main() {
        let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
    
        match msg {
            Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
                "Change the color to red {}, green {}, and blue {}",
                r, g, b
            ),
            Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
                "Change the color to hue {}, saturation {}, and value {}",
                h, s, v
            ),
            _ => (),
        }
    }
    

      

    Destructuring Structs and Tuples

     let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });
    

      

    Ignore 

    忽略整个待匹配值:_

    fn foo(_: i32, y: i32) {
        println!("This code only uses the y parameter: {}", y);
    }

    忽略部分待匹配值:嵌套的_

        match (setting_value, new_setting_value) {
            (Some(_), Some(_)) => {
                println!("Can't overwrite an existing customized value");
            }
            _ => {
                setting_value = new_setting_value;
            }
        }
    

      

    忽略一个没使用过的变量而不输出警告:在变量名前面加_

    fn main() {
        let _x = 5;
        let y = 10;
    }
    

      

    忽略没匹配完的值: ..

     match origin {
            Point { x, .. } => println!("x is {}", x),
        }
    

      

    fn main() {
        let numbers = (2, 4, 8, 16, 32);
    
        match numbers {
            (first, .., last) => {
                println!("Some numbers: {}, {}", first, last);
            }
        }
    }
    

      

    但是要避免二义性:

    fn main() {
        let numbers = (2, 4, 8, 16, 32);
    //error: `..` can only be used once per tuple pattern
        match numbers {
            (.., second, ..) => {
     --          ^^ can only be used once per tuple pattern
                println!("Some numbers: {}", second)
    
            },
        }
    }
    

      

    Match Guards

    match guard是match arm之后接着的一个if条件,要求match arm和if 都被满足时才能够匹配。能够支持比pattern更强大的条件。

    fn main() {
        let x = Some(5);
        let y = 10;
    
        match x {
            Some(50) => println!("Got 50"),
            Some(n) if n == y => println!("Matched, n = {}", n),
            _ => println!("Default case, x = {:?}", x),
        }
    
        println!("at the end: x = {:?}, y = {}", x, y);
    }
    

      

    注意与|连用时,相当于任何一个pattern匹配之后,都要额外匹配这个if语句。

        let x = 4;
        let y = false;
    
        match x {
            4 | 5 | 6 if y => println!("yes"),
    //无论是4,5还是6都需要匹配if y _ => println!("no"), }

      

    @Bindings

    @操作符允许程序员在同一个pattern中把变量保存下来同时测试是否满足条件。基本方法是fieldname: alias @ test_pattern

        enum Message {
            Hello { id: i32 },
        }
    
        let msg = Message::Hello { id: 5 };
    
        match msg {
            Message::Hello {
                id: id_variable @ 3..=7,
            } => println!("Found an id in range: {}", id_variable),
            Message::Hello { id: 10..=12 } => {
    //没有使用@,为了10..=12这个测试,就无法保留named variable
                println!("Found an id in another range")
            }
            Message::Hello { id } => println!("Found some other id: {}", id),
        }
    

      

    Destructuring Structs

  • 相关阅读:
    ans_rproxy 说明
    ubuntu adduser
    linux 修改 elf 文件的dynamic linker 和 rpath
    What Is The Promiscuous Mode
    gpart 分区工具
    TortoiseSVN的基本使用方法
    svn和git的区别及适用场景
    TortoiseSVN 和 VisualSVN Server 使用教程
    SVN中trunk、branches、tag的使用
    C/C++中substr函数的应用(简单讲解)
  • 原文地址:https://www.cnblogs.com/xuesu/p/13888424.html
Copyright © 2020-2023  润新知