Alpha. Vary is under active development and not ready for production use. Syntax, APIs, performance, and behaviour may change between releases.
Error handling
Functions signal problems by raising errors, and callers catch them with try/except blocks. When you want errors as values instead of exceptions, there is also Result[T, E] with Ok and Err variants.
Try / except / finally
def divide(a: Int, b: Int) -> Int {
if b == 0 {
raise ValueError("division by zero")
}
return a // b
}
try {
let result = divide(10, 0)
} except ValueError as e {
print("Bad value")
} except Error as e {
print("Some other error")
} finally {
print("Always runs")
}
except Error: is the broadest catch. Bare except: is not supported. You can raise a string directly: raise "message" wraps it in RuntimeError.
Error types
| Type | Use case |
|---|---|
Error | Base of all Vary errors |
RuntimeError | General runtime errors |
TypeError | Type mismatches |
ValueError | Invalid values |
IOError | I/O failures |
KeyError | Missing dictionary keys |
IndexError | Out-of-bounds access |
ContractViolation | Failed precondition or postcondition |
ProcessError | Subprocess execution failure (not found, permission denied, timeout) |
TimeoutError | Task group exceeded its timeout |
Result type
Result[T, E] represents success or failure without exceptions:
def divide(a: Int, b: Int) -> Result[Int, Str] {
if b == 0 {
return Err("division by zero")
}
return Ok(a // b)
}
let r = divide(10, 3)
assert r.is_ok()
assert r.unwrap() == 3
| Method | Returns | Description |
|---|---|---|
.is_ok() | Bool | True if Ok |
.is_err() | Bool | True if Err |
.unwrap() | T | Unwrap Ok value (panics on Err) |
.unwrap_err() | E | Unwrap Err value (panics on Ok) |
.unwrap_or(default) | T | Unwrap Ok, or return default |
Match on Result with case Ok(value) and case Err(error).
The ? operator
The ? postfix operator unwraps Ok or returns Err early:
def process() -> Result[None, FsError] {
let wp = WritePath.of("/tmp/out.txt")?
let _w = fs.write_text(wp, "hello")?
return Ok(None)
}
The enclosing function must return a Result with the same error type.
The ?else return operator
When unwrapping a Result or optional, ?else return provides a default value and exits the function early if the unwrap fails:
def get_name(id: Int) -> Str {
let user = find_user(id) ?else return "unknown"
return user.name
}
This is useful when the enclosing function does not return a Result and you want a fallback instead of propagating the error.