try
● Intermediate4 minBefore this: ErrorsSpec 5.2
try passes an error on to your own caller: if the call fails, your function fails with the same error.
type AgeError = Empty | NotANumber(text: String)
fn parse_age(text: String) -> Int ! AgeError {
if text.is_empty() {
fail AgeError.Empty
}
Int(text) catch _ => fail AgeError.NotANumber(text: text)
}
fn total_age(a: String, b: String) -> Int ! AgeError {
const first = try parse_age(a)
const second = try parse_age(b)
first + second
}
fn main() {
print(total_age("31", "27") catch -1)
const bad = total_age("31", "x") catch e => {
print("failed: {e}")
-1
}
print(bad)
}The program ran and printed:
kavach run try.kav
58failed: NotANumber(text: "x")-1
total_age calls parse_age twice. Each try means: if this fails, stop here and give the error to my caller. The happy path reads straight down, with no checks in between.
try only works in a function that can fail with that error itself: here, both are ! AgeError.
Methods that take a function that can fail
A built-in method that takes a function (map, filter, sum, sort_by, parallel_map, Shared.update, …) passes that function's error on. Given a function that can fail, the call can fail with its error, and the method stops at the first one:
type PriceError = Unknown(item: String)
fn price(item: String) -> Int ! PriceError {
match item {
"pen" => 10,
"cup" => 25,
_ => fail PriceError.Unknown(item: item),
}
}
fn total(items: [String]) -> Int ! PriceError {
const prices = try items.map(price)
prices.sum(p => p)
}
fn main() {
print(total(["pen", "cup"]) catch _ => 0)
const stopped = total(["pen", "kite", "cup"]) catch e => match e {
PriceError.Unknown(item) => {
print("no price for {item}")
0
},
}
print(stopped)
print(["pen", "kite", "cup"].sum(i => price(i) catch _ => 0))
}The program ran and printed:
kavach run methods-pass-on.kav
35no price for kite035
- The
mapcall is the one that can fail, so it is the one marked, withtryorcatch. - A lambda that handles the error inside, as in the
sum, can't fail, and neither can the call. Shared.updategiven a function that fails leaves the shared value as it was.