Option[T] contains either Some(T) or None.
selected: Option[string] = Some("Atoll")
missing: Option[string] = NoneT? is equivalent and is the preferred compact spelling.
selected: string? = Some("Atoll")
missing: string? = NoneAbsence
Atoll has no null keyword. A value can be absent only when its type admits
absence.
name: string = None // error
name: string? = None // validNested optionals are distinct.
outer: string?? = Nonestring?? is Option[Option[string]]; it can distinguish no outer result from
an outer result containing no string.
Construction
Use Some(value) and None explicitly.
port: int? = Some(8080)An expected optional type can also lift a compatible bare value.
port: int? = 8080The expected type is important for None, because the variant itself does not
identify T.
Match
Match when both cases carry meaningful behavior.
match users.get(0) {
Some(user) => show(user)
None => show_empty_state()
}The checker requires both cases unless an earlier pattern or wildcard covers the remainder.
Conditional patterns
Use an if pattern for one successful branch.
if Some(user) := cache.get(id) {
show(user)
} else {
load(id)
}Use a refutable binding with else when the payload must remain in scope
after the check.
Some(user) := cache.get(id) else {
return None
}
return Some(user.name)The failure block must diverge.
Safe access
?. accesses a field or method only for Some.
city := account?.profile?.cityThe result remains optional. If any receiver in the chain is None, the whole
chain produces None.
This differs from postfix propagation ?, which exits the enclosing optional
function on None.
Fallback
?? extracts a payload or lazily evaluates a fallback.
name := configured_name ?? "anonymous"The right side runs only when the left is None.
??= fills a mutable optional place only when it is absent.
mut label: string? = None
label ??= compute_label()The total methods unwrap_or and unwrap_or_else provide equivalent eager or
lazy fallback APIs.
unwrap_or(default) evaluates default before the call. unwrap_or_else
invokes its zero-argument closure only for None. Prefer the latter when the
fallback is expensive or effectful.
Transformations
Use map to transform a present value while preserving absence.
upper := maybe_name.map { name => name.to_upper_case() }Use flat_map when the callback already returns Option.
email := maybe_user.flat_map { user => user.primary_email }Filtering retains a payload only when a predicate holds.
positive := maybe_number.filter { value => value > 0 }Conversion
to_result(error) converts absence into a typed failure.
user := maybe_user.to_result(NotFound { id })?Some(value) becomes Ok(value); None becomes Err(error).
The error argument to to_result is an ordinary call argument and is therefore
evaluated before the method runs. Use an explicit match when constructing that
error must itself be lazy.
to_list() maps Some(value) to a one-element list and None to an empty
list. flatten() removes one optional layer.
Propagation
Postfix ? extracts Some and returns None from a compatible optional
function.
fn first_name(users: []User): string? {
user := users.get(0)?
return user.name
}It does not convert None into an arbitrary Result error. Perform that
conversion explicitly with to_result.
Representation
The compiler may niche-pack an optional reference-shaped value or use an
explicit tag for an inline scalar/aggregate. That representation does not
change the source cases: every Option[T] is still exactly Some(T) or
None.
Code must not infer presence from a raw address, integer value, or storage layout. Pattern matching and the documented methods are the portable way to observe the tag.