模式匹配

Rust的match非常强大。且有许多特别的用法。

  • | 匹配多个值。
  • ... 匹配一个范围(包含最后一个值)。
  • match中必须存在_。Rust的match强制进行穷尽性检查,必须覆盖所有的可能值
  • 如果需要得到 | 或者 ... 匹配到的值,可以使用@绑定变量。
  • 使用ref关键字来得到一个引用。

例:简单示例

let day = 5;

match day {
  0 | 6 => println!("weekend"),    //  多值匹配
  1 ... 5 => println!("weekday"),  //  范围匹配
  _ => println!("invalid"),        //  任意匹配
}

例:范围匹配

let c = 'w';

match c {
    'a' ... 'z' => println!("小写字母"),
    'A' ... 'Z' => println!("大写字母"),
    _ => println!("其他字符"),
}

例:匹配枚举

enum Direction {
    East,
    West,
    North,
    South,
}

fn main() {
    let dire = Direction::South;

    match dire {
        Direction::East => println!("East"),
        Direction::North | Direction::South => {
            println!("South or North");
        },
        _ => println!("West"),
    };

}

例:匹配值绑定到变量。

let x = 1;

match x {
    e @ 1 ... 5 => println!("got a range element {}", e),  // 绑定变量
    _ => println!("anything"),
}

ref与mut ref

模式匹配过程中,被匹配命中的资源偶未实现Copy的类型就会被的move掉。因此,原owner就不再持有其所有权。但是有些时候,我们只想要从中拿到一个变量的(可变)引用,而不想将其move出作用域,就需要使用refref mut

例:

let x = 5;

// copy值给r。
match x {
    r => println!("Got a reference to {}", r),
}

// 借用值给r。
match x {
    ref r => println!("Got a reference to {}", r),
}

例:

fn main() {
    let x = String::from("hello");

    match x {
        // r => println!("Got a reference to {}", r),  // 引发编译错误。x被move给了r。match后x就无法再被使用。
        ref r => println!("Got a reference to {}", r), // 借用x的资源给r。match后r失效。x依然能用。
    }

    println!("{}",x);

    // 打印:
    // Got a reference to hello
    // hello
}

解构

即将指定数据结构中的数据获取出来。

解构元组

let pair = (0, -2);

match pair {
    (0, y) => println!("x is `0` and `y` is `{:?}`", y),
    (x, 0) => println!("`x` is `{:?}` and y is `0`", x),
    _ => println!("It doesn't matter what they are"),
}

解构枚举

enum Action {
    Say(String),
    MoveTo(i32, i32),
    ChangeColorRGB(u16, u16, u16),
}

fn main() {
    let action = Action::Say("Hello Rust".to_string());

    match action {
        Action::Say(s) => {
            println!("{}", s);
        },
        Action::MoveTo(x, y) => {
            println!("point from (0, 0) move to ({}, {})", x, y);
        },
        Action::ChangeColorRGB(r, g, _) => {
            println!("change color into '(r:{}, g:{}, b:0)', 'b' has been ignored",  r, g);
        }
    }
}

解构结构体

解构一个结构体:

struct Point {
    x: i64,
    y: i64,
}

let point = Point { x: 0, y: 0 };

match point {
    Point { x, y } => println!("({},{})", x, y),
}

对结构体字段更灵活的解构:

match point {
    Point { x: x1, y: y1} => println!("({},{})", x1, y1)  // 直接声明解构字段的变量名称。
}

使用..忽略字段:

match point {
    Point { y, .. } => println!("y is {}", y),
}

match守卫

将if表达式可以放在match的模式之后。

例:

let x = 4;
let y = false;

match x {
    4 | 5 if y => println!("yes"),  // y为false,就算匹配到了4,也不会打印'yes'
    _ => println!("no"),
}

也可以在解构后,对解构值进行条件判断,若通过判断才允许继续执行后面的语句。

enum Action {
    Say(String),
    MoveTo(i32, i32),
    ChangeColorRGB(u16, u16, u16),
}

fn main() {
    let action = Action::MoveTo(1,1);

    match action {
        Action::Say(s) => {
            println!("{}", s);
        },
        Action::MoveTo(x, y) if x < 2 && y < 2 => {
            println!("point from (0, 0) move to ({}, {})", x, y);  // 打印!
        },

        Action::ChangeColorRGB(r, g, _) => {
            println!("change color into '(r:{}, g:{}, b:0)', 'b' has been ignored",  r, g);
        }
        _ => {
            println!("do nothing");
        }
    }

    // 打印:point from (0, 0) move to (1, 1)
}

results matching ""

    No results matching ""