option
import std::core::option; — in the prelude · source
Option<T>
type enum Option<T> {
Some(T);
None;
}
implement enum Option<T> {
is_some(&this) -> boolean;
is_none(&this) -> boolean;
as_ref(&this) -> Option<T*>;
unwrap_ptr(&this) -> T*;
![sink]
unwrap(&this) -> T;
![sink]
expect(&this, message: string) -> T;
![sink]
unwrap_or(&this, default_value: T) -> T;
![sink]
unwrap_or_else(&this, default_fn: () -> T) -> T;
![sink]
map<U>(&this, f: (T) -> U) -> Option<U>;
![sink]
and_then<U>(&this, f: (T) -> Option<U>) -> Option<U>;
![sink]
or_else(&this, f: () -> Option<T>) -> Option<T>;
take(mut &this) -> Option<T>;
![sink]
ok_or<E>(&this, err: E) -> Result<T, E>;
![sink]
ok_or_else<E>(&this, err_fn: () -> E) -> Result<T, E>;
contains(&this, value: &T) -> boolean
where T: Eq;
}
Option<T> is how Cryo says "there might not be a value here". It replaces the nullable pointer: the compiler will not let you reach the payload without handling the absent case.
match (maybe_port) {
Option::Some(p) => { println(f"port {p}"); }
Option::None => { println("no port configured"); }
}
The ![sink] attribute marks the methods that consume the receiver: after opt.unwrap() the move-checker treats opt as moved, even though the parameter is spelled &this. The unmarked methods leave the receiver live.
Querying and unwrapping
| Method | Returns | Notes |
|---|---|---|
is_some / is_none | boolean | |
unwrap | T | Panics on None. |
expect(message) | T | Panics with your message on None. |
unwrap_or(default_value) | T | Returns default_value on None. |
unwrap_or_else(default_fn) | T | Computes the fallback only when needed. |
Borrowing without consuming
unwrap and friends take the value out. When the payload owns heap storage and you only want to look at it, borrow instead:
as_ref(&this) -> Option<T*>—Some(v)becomesSome(&v),NonestaysNone. The pointer aliases the receiver's payload rather than copying it, so the receiver keeps ownership.unwrap_ptr(&this) -> T*— the same borrow, aborting onNone, and one less layer to unwrap.
Both pointers are invalidated by anything that moves or overwrites the receiver.
Transforming
| Method | Returns |
|---|---|
map<U>(f) | Option<U> |
and_then<U>(f) | Option<U> |
or_else(f) | Option<T> |
take() | Option<T> — replaces the receiver with None and returns what was there |
ok_or<E>(err) | Result<T, E> |
ok_or_else<E>(err_fn) | Result<T, E> |
contains(value) (where T: Eq) | boolean |
The ?? operator is sugar over the same idea: opt ?? fallback yields the payload or fallback, evaluating the fallback only on None.
Trait implementations
implement<T> trait Clone for enum Option<T>
where T: Clone
implement<T> trait Eq for enum Option<T>
where T: Eq
implement<T> trait Display for enum Option<T>
where T: Display // std::fmt::display
implement<T> trait Debug for enum Option<T>
where T: Debug // std::fmt::display
Display and Debug both render Some(...) / None; the difference is which trait the payload goes through.