?
によるOption
のアンパック
Option
をアンパックするにはmatch
文を使うこともできますが、?
を使う方が簡単になることが多いでしょう。Option
のx
があるとすると、x?
を評価した値は、x
がSome
の場合はx
に格納された値となり、そうでなければ実行中の関数を終了させ、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? + 1; 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)); }