?でOptionを解析する

match文でOptionを解析できますが、しばしば?演算子を使った方が簡単です。 もしxOptionだとしたら、x?と書けば、xSomeならその値を、そうで なければ現在の関数をNoneを返して終了します。

fn next_birthday(current_age: Option<u8>) -> Option<String> {
	// `current_age`が`None`なら`None`を返す。
	// `current_age`が`Some`なら、`u8`は`next_age`に代入される
    let next_age: u8 = current_age?;
    Some(format!("Next year I will be {}", next_age))
}

コードの可読性をあげるため、?はたくさん連結できます。

struct Person {
    job: Option<Job>,
}

#[derive(Clone, Copy)]
struct Job {
    phone_number: Option<PhoneNumber>,
}

#[derive(Clone, Copy)]
struct PhoneNumber {
    area_code: Option<u8>,
    number: u32,
}

impl Person {

    // その人の仕事用の電話番号のエリアコードを取得します。
    fn work_phone_area_code(&self) -> Option<u8> {
        // `?`演算子がなければ、`match`文をたくさんネストする必要がありました。
        // 簡単に連結を増やすこともできます。試してみてください。
        self.job?.phone_number?.area_code
    }
}

fn main() {
    let p = Person {
        job: Some(Job {
            phone_number: Some(PhoneNumber {
                area_code: Some(61),
                number: 439222222,
            }),
        }),
    };

    assert_eq!(p.work_phone_area_code(), Some(61));
}