diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1969ed05a5..406d348b9a 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -150,6 +150,7 @@ - [Error handling](error.md) - [`panic`](error/panic.md) - [`Option` & `unwrap`](error/option_unwrap.md) + - [Unpacking options with ?](error/option_unwrap/question_mark.md) - [Combinators: `map`](error/option_unwrap/map.md) - [Combinators: `and_then`](error/option_unwrap/and_then.md) - [`Result`](error/result.md) diff --git a/src/error/option_unwrap/question_mark.md b/src/error/option_unwrap/question_mark.md new file mode 100644 index 0000000000..7cff868ad6 --- /dev/null +++ b/src/error/option_unwrap/question_mark.md @@ -0,0 +1,55 @@ +# Unpacking options with ? + +You can unpack Options by using `match` statements, but it's often easier to use the `?` operator. If `x` is an `Option`, then evaluating `x?` will return the underlying value if `x` is Some, otherwise it will terminate whatever function is being executed and return `None`. + +```rust,editable +fn next_birthday(current_age: Option) -> Option { + // If `current_age` is None, this returns None. + // If `current_age` is Some, the inner u8 gets assigned to `next_age` + let next_age: u8 = current_age?; + Some(format!("Next year I will be {}", next_age)) +} +``` + +You can chain many ?s together to make your code much more readable. + +```rust,editable +struct Person { + job: Option, +} + +#[derive(Clone, Copy)] +struct Job { + phone_number: Option, +} + +#[derive(Clone, Copy)] +struct PhoneNumber { + area_code: Option, + number: u32, +} + +impl Person { + + // Gets the area code of the phone number of the person's job, if it exists. + fn work_phone_area_code(&self) -> Option { + // This would need many nested `match` statements without the ? operator. + // It would take a lot more code - try writing it yourself and see which + // is easier. + 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)); +} +``` \ No newline at end of file