?로 옵션 풀기
match 문을 사용하여 Option을 풀 수(unpack) 있지만, ? 연산자를 사용하는 것이 더 쉬울 때가 많습니다. 만약 x가 Option이라면, x?를 평가할 때 x가 Some이면 그 내부 값을 반환하고, 그렇지 않으면 실행 중인 함수를 종료하고 None을 반환합니다.
fn next_birthday(current_age: Option<u8>) -> Option<String> {
// 만약 `current_age`가 `None`이면, 이는 `None`을 반환합니다.
// 만약 `current_age`가 `Some`이면, 내부의 `u8` 값 + 1이
// `next_age`에 할당됩니다.
let next_age: u8 = current_age? + 1;
Some(format!("내년에 저는 {}살이 됩니다", next_age))
}
여러 개의 ?를 체인으로 연결하여 코드를 훨씬 더 읽기 쉽게 만들 수 있습니다.
struct Person {
job: Option<Job>,
}
#[derive(Clone, Copy)]
struct Job {
phone_number: Option<PhoneNumber>,
}
#[derive(Clone, Copy)]
#[allow(dead_code)]
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));
}