Skip to content
Kavachकवच

catch

● Intermediate4 minBefore this: ErrorsSpec 5.3

catch handles an error on the spot: give a value to use instead, or run code with the error.

A value to use instead

fn half(n: Int) -> Int ! String {
    if n % 2 != 0 {
        fail "odd: {n}"
    }
    n / 2
}

fn main() {
    print(half(10) catch 0)
    print(half(7) catch 0)
}

The program ran and printed:

kavach run default.kav

50
default.kav: Kavach code, then what running it prints

Code that sees the error

fn half(n: Int) -> Int ! String {
    if n % 2 != 0 {
        fail "odd: {n}"
    }
    n / 2
}

fn main() {
    const b = half(7) catch e => {
        print("could not: {e}")
        0
    }
    print(b)
}

The program ran and printed:

kavach run handle.kav

could not: odd: 70
handle.kav: Kavach code, then what running it prints

Skip and carry on

A handler can also leave: continue skips to the next round of a loop, return leaves the function.

fn main() {
    const lines = ["12", "oops", "30", "", "8"]
    let total = 0
    for line in lines {
        const n = Int(line) catch _ => {
            continue
        }
        total += n
    }
    print(total)
}

The program ran and printed:

kavach run skip.kav

50
skip.kav: Kavach code, then what running it prints

Only the call's own error

A call's catch handles that call's own error, never one raised while its arguments are worked out. A try in an argument leaves the function, as it would with no catch around the call:

type ParseError = Empty | NotANumber
type LookupError = Missing(id: Int)

fn parse(text: String) -> Int ! ParseError {
    if text.is_empty() {
        fail ParseError.Empty
    }
    Int(text) catch _ => fail ParseError.NotANumber
}

fn lookup(id: Int) -> String ! LookupError {
    if id == 7 {
        return "pens"
    }
    fail LookupError.Missing(id: id)
}

fn find(text: String) -> String ! ParseError {
    lookup(try parse(text)) catch e => "nothing: {e}"
}

fn main() {
    for text in ["7", "8", "x"] {
        print(find(text) catch e => "find failed: {e}")
    }
}

The program ran and printed:

kavach run catch-own-error.kav

pensnothing: Missing(id: 8)find failed: NotANumber
catch-own-error.kav: Kavach code, then what running it prints
  • e is a LookupError: 8 is parsed, then not found, and the catch handles that.
  • x can't be parsed, so try leaves find with the ParseError, and its caller handles it.
tested