Optional
Typed presence or absence, explicit checked payload access, managed identity and ownership, and time and space complexity.
Optional<T> is an import free typed value that explicitly contains a value of T or contains no value. It represents missing scalar, object, and native values without assigning a sentinel number or overloading an empty String.
Construction and checked access
let missing: Optional<Float64> = Optional.none<Float64>()
let measured = Optional.some(3.5)
print(missing.is_none()) // true
print(measured.is_some()) // true
print(missing.unwrap_or(default: 0.0)) // 0.0
if measured.is_some() {
print(measured.unwrap()) // 3.5
}Optional.some<T>(value: T) constructs a present value. T can be inferred from the supplied concrete value. Optional<T>(value: T) is an equivalent constructor. Optional.none<T>() requires an explicit payload type because absence supplies no value from which to infer it. Type annotations do not convert a payload into another datatype.
A payload may have a scalar, native, user class, collection, or nested generic type. The wrapper retains that declared concrete type. A present nullable payload and an absent Optional remain distinct concepts. Optional is separate from existing nullable class references and dataset column missingness; those existing contracts retain their own accessors and checks.
| Method | Result | Contract |
|---|---|---|
is_some() | Bool | Whether the wrapper contains a payload. |
is_none() | Bool | Whether the wrapper is absent. |
unwrap() | T | Return the present payload; absence produces a located runtime error. |
unwrap_or(default: T) | T | Return the payload when present, otherwise the supplied same type default. |
Access is explicit and checked. Testing is_some() does not automatically change the wrapper's static type or remove the need for a payload accessor. unwrap_or is an ordinary call: its default expression is evaluated even when the Optional is present. This release does not add pattern matching, a propagation operator, or a lazy default callback.
Ownership and type inspection
An Optional is an immutable managed wrapper. Copies share the wrapper's identity. A reference payload retains its existing ownership: for example, a wrapped List remains a mutable shared List, and wrapping it does not deep freeze or copy the collection. The execution heap traces wrapped references, including reachable cycles, using the same object and slot limits as other managed values.
Equality compares wrapper identity, without invoking payload equality or user code. Separately constructed present wrappers are therefore distinct even when their payloads are equal. Compare checked payloads explicitly when payload value equality is required. Wrappers are not scalar Dictionary keys or Set members.
type(value) reports the concrete specialization, such as Optional<Float64>. cast<Optional<Float64>>(value) checks that specialization when recovering a value from Any. dtype is unsupported for Optional: a payload type is not a homogeneous element storage datatype.
Errors and limits
Unchecked access to an absent alternative or a wrapper operation limit failure produces a located runtime error R3404. Wrong static argument types or arities produce E1002. Generic wrapper nesting is limited to 128 and formatted type names to 16 KiB; exceeding these static bounds produces E1007. Shared managed object and value slot limits also apply. A runtime failure retains the normal program or persistent session error contract.
Time and space complexity
The wrapper retains O(1) active state metadata and zero or one payload slot, plus its generic type descriptor. Let g describe the materialized generic type descriptor or name length. Construction and descriptor copying can add O(g) time and space. Presence tests and identity comparison use O(1) active state work plus O(g) receiver descriptor validation at the heap boundary; access adds that validation and the returned payload copy cost. Payload evaluation and copying follow the payload's existing semantics; an owned String can add O(b) byte time and storage, while reference payloads share their existing object. Managed garbage collection adds its normal reachable object and slot traversal cost. Unwrapping does not materialize an entire collection.
Run the complete Optional example, and see Result for a typed recoverable error outcome.