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
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
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
50Only 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
eis aLookupError:8is parsed, then not found, and thecatchhandles that.xcan't be parsed, sotryleavesfindwith theParseError, and its caller handles it.