Optionals: What an optional is
● Intermediate3 min
T? means a T or none. Lookups that can find nothing give one.
fn main() {
const names = ["Asha", "Ravi"]
print(names.get(5) ?? "nobody")
const ages = ["asha": 31]
print(ages["asha"] ?? 0)
print(ages["omar"] ?? 0)
}The program ran and printed:
kavach run optionals-lookups.kav
nobody310
Using the value without saying what to do when it is missing is refused:
fn main() {
const ages = ["asha": 31]
const next = ages["asha"] + 1
print(next)
}The compiler refused the program:
kavach run optionals-must-check.kav
error: expected a number, found `Int?`: it may be `none`, so give a default with `?? 0`, or check it with `if let` (spec 2.7)A value where an optional is wanted
A T can be used wherever a T? is wanted: in a variable, as a lambda's result, and as the value of a Shared<T?>:
type Node {
name: String
}
fn main() {
const nickname: String? = "Ash" // a String where a String? is wanted
print(nickname ?? "none")
const pick: fn(Int) -> String? = _ => "x"
print(pick(1) ?? "none")
const held: Shared<Node?> = Shared(Node(name: "b"))
print(held.get()?.name ?? "none")
held.update(_ => Node(name: "a"))
print(held.get()?.name ?? "none")
}The program ran and printed:
kavach run optional-fill.kav
Ashxba
A Shared<Node> that is already made can't be stored where a Shared<Node?> is wanted. Every copy of a Shared sees one value, and through the new type, none could be put in it. Make it with the optional type from the start:
type Node {
name: String
}
fn main() {
const made: Shared<Node> = Shared(Node(name: "b"))
const held: Shared<Node?> = made
print(held.get()?.name ?? "none")
}The compiler refused the program:
kavach run optional-fill-shared.kav
error: expected `Shared<Node?>`, found `Shared<Node>`: every copy of a `Shared` sees one value, so its type can't change; make it as `Shared<Node?>` from the start