Error Handling
Ferret uses explicit error handling with Error Types to manage failures safely.
Result Types
Section titled “Result Types”Functions or methods that can fail return E ! T (Result type), where E is the error type and T is the success type.
The syntax is consistent with the error return operator: just as you write return "error"! to return an error, you write E ! T for the type.
fn divide(a: i32, b: i32) -> str ! i32 { if b == 0 { return "Division by zero"!; // The `!` operator constructs an error value } return a / b;}Both types are required - you must specify both the error type and success type.
Handling Errors
Section titled “Handling Errors”When calling a function that returns an error type, you cannot ignore the possibility of failure. For example, this won’t compile:
let result := divide(10, 2); // You cannot call the function without handling the errorSo you must handle it using catch clause:
let result := divide(10, 0) catch e { // e holds the error value // Handle error case io::Println("Error occurred: " + e); return; // Early return};
// These line won't reach if there was an errorio::Println("Result: " + result); // won't run because the program will return early on errorBut what if you want to move forward even with an error? You can provide a default value after the catch block. This can be either declared in the block or after it as literal value:
let result := divide(10, 0) catch e { // handle error case and provide default io::Println("Error occurred: " + e); let default_value := -1;} default_value; // result will be -1Or more concisely:
let result := divide(10, 0) catch e { // handle error case and provide default io::Println("Error occurred: " + e);} -1 ; // default value if error occurs, result will be -1Shorthand
Section titled “Shorthand”You can just provide the default value directly:
let result := divide(10, 0) catch -1; // result will be -1 on error