Error Handling
Source: examples/error_handling.ion in the repo.
// Error handling with Result, Option, and ? operator
// Parsing with Result matchingfn parse_point(input) { let parts = input.split(","); if parts.len() != 2 { return Err("expected 'x,y' format"); } match (parts[0].trim().to_int(), parts[1].trim().to_int()) { (Ok(x), Ok(y)) => Ok((x, y)), (Err(e), _) => Err(f"bad x: {e}"), (_, Err(e)) => Err(f"bad y: {e}"), }}
// Test various inputslet inputs = ["3, 4", "10,20", "bad,5", "1,2,3"];for input in inputs { match parse_point(input) { Ok((x, y)) => io::println(f" '{input}' -> point({x}, {y})"), Err(e) => io::println(f" '{input}' -> error: {e}"), }}
// Option chainingfn lookup(db, key) { db.get(key)}
let db = #{ alice: #{age: 30, role: "admin"}, bob: #{age: 25, role: "user"},};
let alice_age = lookup(db, "alice") .map(|user| user.age);io::println(f"\nAlice's age: {alice_age}");
let unknown = lookup(db, "charlie");io::println(f"Charlie: {unknown}");
// unwrap_or for defaultslet name = None.unwrap_or("anonymous");io::println(f"Name: {name}");
let val = Some(42).unwrap_or(0);io::println(f"Value: {val}");
// Result methodsfn safe_divide(a, b) { if b == 0 { Err("division by zero") } else { Ok(a / b) }}
let result = safe_divide(10, 3) .map(|n| n * 100) .unwrap_or(0);io::println(f"\n10/3 * 100 = {result}");
let fallback = safe_divide(10, 0).unwrap_or(-1);io::println(f"10/0 with fallback: {fallback}");
// is_ok / is_errio::println(f"10/3 is_ok: {safe_divide(10, 3).is_ok()}");io::println(f"10/0 is_err: {safe_divide(10, 0).is_err()}");
// map_errlet tagged = safe_divide(10, 0) .map_err(|e| f"math error: {e}");io::println(f"Tagged error: {tagged}");
// ---- The ? operator ----// ? unwraps Ok/Some, propagates Err/None to the caller
fn parse_and_double(s) { let n = s.to_int()?; Ok(n * 2)}
let r1 = parse_and_double("5");let r2 = parse_and_double("abc");io::println(f"\nparse_and_double('5') = {r1}"); // Ok(10)io::println(f"parse_and_double('abc') = {r2}"); // Err(...)
// Chained ? across function boundariesfn compute(input) { let point = parse_point(input)?; let (x, y) = point; Ok(x + y)}
let c1 = compute("3,4");let c2 = compute("bad,5");let c3 = compute("1,2,3");io::println(f"compute('3,4') = {c1}"); // Ok(7)io::println(f"compute('bad,5') = {c2}"); // Err(bad x: ...)io::println(f"compute('1,2,3') = {c3}"); // Err(expected 'x,y' format)
// ? with Optionfn first_even(items) { let first = items.first()?; if first % 2 == 0 { Some(first) } else { None }}
io::println(f"\nfirst_even([4,5,6]) = {first_even([4, 5, 6])}"); // Some(4)io::println(f"first_even([3,5,7]) = {first_even([3, 5, 7])}"); // Noneio::println(f"first_even([]) = {first_even([])}"); // None