#Option
Status: standard library specification draft.
This chapter defines the part of std.option that lib/std writes in
ordinary hd over the language tier. That is the inherent methods
and_then, unwrap_or, or, ok_or, is_some, is_none, and expect
of T?.
The language tier keeps what the compiler knows by name (Optional Types):
| Item | Why it stays in the language tier |
|---|---|
Option[T], T?, .Some, and .None |
the prelude enum, its sugar, and its construction rules |
| implicit wrapping and nesting | Implicit Wrapping And Nesting |
postfix ? on an optional |
Representation And Propagation |
invariance in T |
types.option.invariant |
map on T? is in List And Optional Map.
#Optional Methods
std.option gives every T? three more methods:
fn first_even(values: List[i32]) -> i32?:
for value in values:
if value % 2 == 0:
return .Some(value)
.None
fn quarter(value: i32) -> i32?:
if value % 4 == 0: .Some(value / 4) else: .None
fn quarter_of_first_even(values: List[i32]) -> i32:
first_even(values).and_then(quarter).unwrap_or(0)| Rule | Method | Result |
|---|---|---|
std-option.and-thenand_then |
fn and_then[U](self, transform: fn(T) -> U?) -> U? |
transform(value) for .Some(value), and .None for .None |
std-option.unwrap-orunwrap_or |
fn unwrap_or(self, fallback: T) -> T |
value for .Some(value), and fallback for .None |
std-option.oror |
fn or(self, other: T?) -> T? |
the optional itself for .Some(_), and other for .None |
- std-option.methods.inherentAll three are inherent methods that
stddeclares onT?, so every optional has them without ause, bytrait.own.inherent.std.no-use. - std-option.and-then.once
and_thencallstransformonce for.Some, and never for.None. - std-option.and-then.flat
and_thenadds no optional layer: its result is theU?thattransformreturns, not aU??. - std-option.methods.non-suspendingNo method suspends. The
transformcallback is a plain function type with the empty row. - std-option.or.layers
orreturns an optional, not aT, so calls chain:flag.or(variable).or(fixed)is.Someof the first present value, and.Nonewhen all are.None.
Note.
fallbackandotherare ordinary arguments, so each is evaluated before the call, even when the optional is present.
Why. Postfix
?works only where the enclosing function or closure returns an optional.and_thenchains two optional steps in any expression, as Rust'sOption::and_thendoes.orlayers fallbacks, as Rust'sOption::ordoes; a costly fallback is amatch, which is lazy.
#Variant Tests And Conversions
std.option also gives every T? four methods that test the variant, or
turn it into a value:
fn port(text: string?) -> Result[string, string]:
text.ok_or("no port given")
fn greeting(name: string?) -> string:
if name.is_none():
return "hello"
known := name.expect("checked above")
"hello, ${known}"| Rule | Method | Result |
|---|---|---|
std-option.ok-orok_or |
fn ok_or[E](self, error: E) -> Result[T, E] |
.Ok(value) for .Some(value), and .Err(error) for .None |
std-option.is-someis_some |
fn is_some(self) -> bool |
true for .Some(_), and false for .None |
std-option.is-noneis_none |
fn is_none(self) -> bool |
false for .Some(_), and true for .None |
std-option.expectexpect |
fn expect(self, message: string) -> T |
value for .Some(value), and a panic for .None |
- std-option.tests.inherentThe four are inherent methods that
stddeclares onT?as well, so they need nouseeither. - std-option.expect.panic
expecton.Nonecallspanic(message), so its category isexplicit-panic. Panic:explicit-panic. - std-option.tests.non-suspendingNone of the four suspends.
Note.
errorandmessageare ordinary arguments, so each is evaluated before the call, whichever variant the optional holds.
Why.
ok_orjoins an optional step to a fallible one, as Rust'sOption::ok_ordoes.expectnames the broken assumption in its panic message, where a barematchwould repeat it at every call.
#Optional Context
context turns a .None into an error with a message, as anyhow's
Context does for Option:
use std.error.Error
fn first_word(words: List[string]) -> Result[string, *dyn Error]:
word := words.first().context("no words")?
.Ok(word)For an empty list, first_word returns an error that displays as no words.
- std-option.context.reference-result
stddeclares the inherent methodpub fn context(self, text: string) -> Result[T, *dyn Error]onT?, so every optional has it without ause, bytrait.own.inherent.std.no-use. - std-option.context.some
.Some(value).context(text)returns.Ok(value). - std-option.context.none-reference
.None.context(text)returns.Err(message(text)), wheremessageisstd-error.message.reference. - std-option.context.non-suspending
contextdoes not suspend.
Note.
textis an ordinary argument, evaluated before the call, whichever variant the optional holds.
Why. An optional step in a function that returns
Result[T, *dyn Error]otherwise needsok_orand an error type.
See also: Result, Runtime Panics, Variance.