Skip to content
Kavachकवच

Optionals: Reading one safely

● Intermediate3 min

Read an optional with ?? for a default, ?. to read through, or if let to act only when it is there.

type User {
    name: String
}

fn find_user(id: Int) -> User? {
    if id == 7 { User(name: "Asha") } else { none }
}

fn main() {
    const found = find_user(7)
    const missing = find_user(8)
    print(found?.name ?? "guest")
    print(missing?.name ?? "guest")
    if let u = find_user(7) {
        print("Found {u.name}")
    }
}

The program ran and printed:

kavach run optionals-basic.kav

AshaguestFound Asha
optionals-basic.kav: Kavach code, then what running it prints

There is also .unwrap(): the value, or a panic when it is none. Outside test blocks and example clauses it gets a warning, because the panic would say nothing of why:

fn find(id: Int) -> Int? {
    if id == 1 { 7 } else { none }
}

fn main() {
    print(find(1).unwrap())
}

The compiler warned, then the program ran:

kavach run unwrap.kav

warning: `.unwrap()` panics on `none` and says nothing of why. Handle `none` with `if let`, `match` or `?? default`, or say why it can't happen: `?? panic("…")` (spec 2.7)7
unwrap.kav: Kavach code, then what running it prints

Handle none with ??, ?., if let or match, or say why it can't happen with ?? panic("…"). And on a value the compiler already knows is none, .unwrap() won't even compile: see Kinds of Errors.

Optionals don't nest

A T?? is a T?. So reading an optional field through an optional value gives one none, not two: e?.time, where time is an Int?, is an Int?. It is none when there is no event, and when the event has no time:

type Event {
    name: String
    time: Int?
}

fn time_of(e: Event?) -> Int? {
    e?.time
}

fn main() uses Console {
    print(time_of(Event(name: "start", time: 5)) ?? -1)
    print(time_of(Event(name: "later", time: none)) ?? -1)
    print(time_of(none) ?? -1)
}

The program ran and printed:

kavach run optionals-flat.kav

5-1-1
optionals-flat.kav: Kavach code, then what running it prints
tested