// 06_error_handling.ruchy - Error handling with Result and Option
fn main() {
println("=== Error Handling ===\n")
// Using Option type
println("=== Option Type ===")
fn find_user(id) {
if id == 1 {
Some("Alice")
} else {
None
}
}
let user1 = find_user(1)
let user2 = find_user(999)
match user1 {
Some(name) => println(f"Found user: {name}"),
None => println("User not found")
}
// Using if-let with Option
if let Some(name) = user1 {
println(f"User exists: {name}")
}
// Using Result type
println("\n=== Result Type ===")
fn divide(a, b) {
if b == 0 {
Err("Division by zero")
} else {
Ok(a / b)
}
}
let result1 = divide(10, 2)
let result2 = divide(10, 0)
match result1 {
Ok(value) => println(f"10 / 2 = {value}"),
Err(msg) => println(f"Error: {msg}")
}
match result2 {
Ok(value) => println(f"Result: {value}"),
Err(msg) => println(f"Error: {msg}")
}
// Try-catch blocks
println("\n=== Try-Catch ===")
fn risky_operation(x) {
if x < 0 {
throw "Negative value not allowed"
}
x * 2
}
try {
let result = risky_operation(5)
println(f"Success: {result}")
} catch e {
println(f"Caught error: {e}")
}
try {
let result = risky_operation(-1)
println(f"Success: {result}")
} catch e {
println(f"Caught error: {e}")
}
// The ? operator for error propagation
println("\n=== Error Propagation with ? ===")
// Helper function that returns Result - wraps to_int with try/catch
fn try_parse_int(s) {
try {
Ok(s.to_int())
} catch e {
Err(f"Failed to parse: {e}")
}
}
fn parse_and_double(s) -> Result {
let num = try_parse_int(s)?
Ok(num * 2)
}
let good = parse_and_double("21")
let bad = parse_and_double("not a number")
match good {
Ok(v) => println(f"Parsed and doubled: {v}"),
Err(e) => println(f"Failed: {e}")
}
match bad {
Ok(v) => println(f"Parsed and doubled: {v}"),
Err(e) => println(f"Failed to parse: {e}")
}
// Custom error types
println("\n=== Custom Errors ===")
fn validate_age(age) {
if age < 0 {
Err("Age cannot be negative")
} else if age > 150 {
Err("Age seems unrealistic")
} else {
Ok(age)
}
}
let ages = [-5, 25, 200]
for age in ages {
match validate_age(age) {
Ok(a) => println(f"Valid age: {a}"),
Err(msg) => println(f"Invalid age {age}: {msg}")
}
}
// Chaining Result operations
println("\n=== Chaining Results ===")
fn step1(x) {
if x > 0 {
Ok(x * 2)
} else {
Err("Step 1 failed")
}
}
fn step2(x) {
if x < 100 {
Ok(x + 10)
} else {
Err("Step 2 failed")
}
}
fn process(input) {
match step1(input) {
Ok(v1) => match step2(v1) {
Ok(v2) => println(f"Final result: {v2}"),
Err(e) => println(f"Error in step 2: {e}")
},
Err(e) => println(f"Error in step 1: {e}")
}
}
process(10)
process(-5)
process(60)
}