leviathan-lang.com / docs / learn
No null: optionals
Absence as a typed value, the ?? and ?. operators, and narrowing by flow typing.
Absence is a value
Leviathan has no null. Absence is a real, typed value called None, and T? is simply sugar
for the union T | None. Because absence is in the type, the compiler makes you handle it. You
cannot quietly forget.
A value that may be absent
string? header(string name) => name == "Authorization" ? "secret" : None;
string? token = header("Authorization"); // maybe there, maybe not
// token.length(); // compile error: must handle the None case first
console.writeln(token ?? "none");
console.writeln(header("Cookie") ?? "none");
secret
none
Defaults and short-circuits
Two operators cover the common cases. ?? supplies a default when a value is None; ?.
short-circuits a call or access to None.
?? and ?.
string? token = "abc";
string? missing = None;
string shown = token ?? "anonymous"; // fall back to a default
string other = missing ?? "anonymous";
int? len = token?.length(); // None if token is None
int? none = missing?.length();
console.writeln(shown);
console.writeln(other);
console.writeln(len);
console.writeln(none);
abc
anonymous
3
None
Narrowing by flow typing
For anything richer, narrow by flow typing. Once you have checked, the compiler tracks that the
value is present inside that branch, including across && and along member paths.
Narrowing with != None
string? token = "abc";
if (token != None && token.length() > 0) {
console.writeln("authorized: ${token}"); // token is a plain string here
} else {
console.writeln("no credentials");
}
string? missing = None;
if (missing != None && missing.length() > 0) {
console.writeln("authorized: ${missing}");
} else {
console.writeln("no credentials");
}
authorized: abc
no credentials
Conditions must be bool: there is no "truthiness." An empty string, a zero, and None are all
distinct and none of them is secretly false. The reference entry on unions and optionals has the
full narrowing rules.
See also
- Unions and optionals — Closed unions
T | U, the optionalT?, narrowing with!= Noneandis, and the??and?.operators.