Skip to content
On this page

枚举和匹配

Enum

rust
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);

let loopback = IpAddr::V6(String::from("::1"));

可以这么理解,IpAddr::V4() 是一个函数调用,以 String 为参数返回 IpAddr 类型。

rust
impl Message {
    fn call(&self) {
        // method body would be defined here
    }
}

let m = Message::Write(String::from("hello"));
m.call();

Option

标准库自带一个叫 Option<T> 的 Enum,用于处理数据可能为空的情况。

rust
enum Option<T> {
    None,
    Some(T),
}

OptionSomeNone 都通过 prelude 自动带入作用域,不需要手动引入。

注意 5Some(5) 并不是一个东西,不能直接相加,需要后续处理才能使用,这也强迫你尽量处理 None 的情况,当然你还是可以逃课的,但前提是你必须知道你在做什么。

match

rust
#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("State quarter from {:?}!", state);
            25
        }
    }
}

上例就是对 coin 的值进行匹配,并运行函数。对于传入了值的 Quarter,运行函数时就直接把值当成参数传进去了(其实,也挺符合直觉的)。

Option 的 match

rust
fn main() {
    fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }

    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
}

在使用 match 时,你必须处理可能匹配到的所有情况,否则编译报错。

rust
fn main() {
    let dice_roll = 9;
    match dice_roll {
        3 => add_fancy_hat(),
        7 => remove_fancy_hat(),
        other => move_player(other),
        // _ => reroll(),
    }

    fn add_fancy_hat() {}
    fn remove_fancy_hat() {}
    fn move_player(num_spaces: u8) {}
}

匹配所有情况不代表要把所有选项都写一遍,使用 other_ 可以简单处理剩余所有情况。

if let

match 处理所有情况相反,if let 用于更方便地处理某一特定情况,其他情况全部 else

rust
fn main() {
    let coin = Coin::Penny;
    let mut count = 0;
    if let Coin::Quarter(state) = coin {
        println!("State quarter from {:?}!", state);
    } else {
        count += 1;
    }
}