Option
Absence is a value, Some(value) or None, and there is no null: a value wraps itself into Some where an Option is expected, and an Option is only ever unwrapped on purpose.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Option<Value> is a value that may or may not be there: Some(value) when it is, None when it is not. Value? is
sugar for Option<Value>, and there is nothing else that models absence - no null, no nil, no implicit
unwrapping. A value where an Option of its type is expected becomes Some(value) on its own.
Example#
const found: Int? = 3
const missing: Int? = None
print found.isSome()
print missing.isNone()
print found.orElse(0)
print "{found} {missing}"Syntax#
Value? Option<Value>
value a present value, where an Option<Value> is expected
Some(value) a present value, written out
None an absent valueRules#
Option<Value>has exactly two cases,Some(value: Value)andNone.SomeandNoneare bare in an expression and in a pattern, because the prelude imports both.A value where an
Optionof its type is expected becomesSome(value). The result of a body andreturn, a binding with an annotation, an argument, a field and a collection element all wrap a plain value, soSomeis written only where the value is anOptionitself or its type is not decided yet.Noneis always written. See Conversions, rule 8.fn half(value: Int): Int? { if value % 2 != 0 { return None } value / 2 } const scores: List<Int?> = [3, None, 5] print "{half(8)} {half(3)} {scores}"isSome()andisNone()ask which case it is;map,flatMapandfiltertransform without unwrapping.mapruns its closure on the value if there is one and staysNoneotherwise;flatMapismapfor a closure that itself returns anOption;filterturnsSomeintoNonewhen the predicate fails.const found: Int? = 3 print found.map({ _ * 2 }) print found.flatMap({ value => if value > 0 { Some value } else { None } }) print found.filter({ _ > 0 })orElseis the??operator, and its fallback is lazy.found ?? 0andfound.orElse(0)are the same call; the fallback expression only runs when theOptionisNone.okOrturns anOptioninto aResult, with a lazy error for theNonecase.expectunwraps or panics with the message given, for the cases where absence would be a bug rather than an outcome.const found: Int? = 3 print found.okOr("missing") print found.expect("should be there")toList()turns anOptioninto a list of zero or one elements, which is the way into a pipeline:map,filterand the rest ofIterateall follow from there once the value is aList.The generated
ShowwritesSome(value)or the bareNone. A case with fields is written out, a case without one is its name - the same rule every other case follows.Value??is anOptionof anOption. Each?wraps once, soInt??isOption<Option<Int>>:Noneis "nothing was looked up",Some(None)is "it was looked up and there was nothing". In an expression??is the fallback; in a type position it is two?. The innerSomeis always written - anOptionnever wraps into another one, and the payload of a writtenSomenever wraps itself - soSome(Some(3))is the one spelling.fn describe(lookup: Int??): String { match lookup { Some(Some(value)) => "found {value}" Some(None) => "looked up, nothing there" None => "never looked up" } } print describe(Some(None))
What this is not#
An Option is not implicitly its value. A value wraps into an Option where one is expected, but the way back
is always written: ??, ?, match or if const.
const found: Int? = 3
print(found ?? 0)const found: Int? = 3
const plain: Int = found
// error: Expected `Int64`, found `Option<Int64>`A value does not wrap twice. An Int where an Int?? is expected is an error, not Some(Some(value)):
const nested: Int?? = 3
// error: Expected `Option<Option<Int64>>`, found `Int64`None is not null, and it does not compare equal to every type. Option<Int> and Option<String> are
different types, each with its own None; a None never stands for "no value of any type".
Related#
- Void and Never - the other two types with no ordinary constructor.
- Bindings - how
?on a type annotation reads asOption. - Result -
Ok/Fail, the typeOption.okOrconverts into.