← All Examples Types

Error Handling

JAPL has no exceptions. Errors are values, represented as algebraic types. Pattern matching forces you to handle both success and failure at every call site.

Source Code

type MyResult =
  | MyOk(Int)
  | MyErr(String)

fn divide(a: Int, b: Int) -> MyResult {
  if b == 0 { MyErr("division by zero") }
  else { MyOk(a / b) }
}

fn main() {
  match divide(10, 2) {
    MyOk(n) => println("10/2 = " <> show(n))
    MyErr(e) => println("Error: " <> e)
  }
  match divide(10, 0) {
    MyOk(n) => println("10/0 = " <> show(n))
    MyErr(e) => println("Error: " <> e)
  }
}

What This Demonstrates

Line-by-Line Breakdown

type MyResult = | MyOk(Int) | MyErr(String)
A result type with two variants: MyOk wraps a successful Int value; MyErr wraps an error message string.
fn divide(a: Int, b: Int) -> MyResult
A safe division function. Instead of crashing on division by zero, it returns a MyErr value.
if b == 0 { MyErr("division by zero") }
Guards against the error case and returns a descriptive error value.
else { MyOk(a / b) }
The happy path wraps the result in MyOk.
match divide(10, 0) { MyOk(n) => ... MyErr(e) => ... }
The caller must handle both cases. Trying to use the value without matching would be a compile error.

Try Modifying