Skip to content
Kavachकवच

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
optionals-lookups.kav: Kavach code, then what running it prints

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)
optionals-must-check.kav: Kavach code, then what running it prints

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
optional-fill.kav: Kavach code, then what running it prints

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
optional-fill-shared.kav: Kavach code, then what running it prints