Error Handling
LuneScript provides mechanisms for developing robust applications, ranging from simple error representation
using nil to type-safe __Ret types and the "error delegation" feature for
efficient handling.
__Ret<T, E> Type
__Ret<T, E> is an algebraic data type (ADT) used to represent a value upon success (Ok)
and error information upon failure (Err) in a single type. It is equivalent to Rust's
Result<T, E>.
// Conceptual internal definition
alge __Ret<T, E> {
Ok( val: T ),
Err( err: E ),
}
Basic Usage
Use .Ok(value) to return a value and .Err(error) to return an error. The receiving
side can decompose it safely with a match statement.
fn divide( a: real, b: real ): __Ret<real, str> {
if b == 0.0 {
return .Err( "division by zero" );
}
return .Ok( a / b );
}
let result = divide( 10.0, 0.0 );
match result {
case .Ok( val ) { print( "Success:", val ); }
case .Err( msg ) { print( "Error:", msg ); }
}
__Er Type
When detailed information such as position information is needed as error info instead of a simple string,
using the standard __Er type is recommended.
fn sub(): __Ret<int, __Er> {
return .Err( __serr( "something went wrong" ) );
}
Error Delegation (! Operator)
When calling functions that may cause errors in succession, checking with match or
if every time makes the logic hard to read. The ! operator automates this check.
Principle of Operation
When ! is appended to the end of an expression, the compiler behaves as if it generated the
following code:
- If the value is Normal (Ok or non-nil), extract that value and continue processing.
- If the value is an Error (Err or nil), immediately return that error from the current function and exit.
fn step1(): __Ret<int, str> { return .Ok(1); }
fn step2(val: int): __Ret<int, str> { return .Ok(val + 1); }
fn series(): __Ret<int, str> {
// If step1() is Err, immediately return .Err(...)
let res1 = step1()!;
// Same for step2(). If normal, res2 gets the value
let res2 = step2( res1 )!;
return .Ok( res2 );
}
Combining with Nilable
The ! operator can also be used with Nilable types (T!). In this case, the return
value of the current function must also be Nilable.
fn getVal(): int! { return nil; }
fn process(): int! {
let val = getVal()!; // If getVal() is nil, immediately return nil
return val + 1;
}
Guidelines for Usage
| Method | Suitable Cases | Features |
|---|---|---|
| Nilable (T!) | Simple absence, or when error content is obvious. | Most lightweight and convenient. |
| Multiple Returns (T!, str!) | When prioritizing compatibility with common Lua styles. | High Lua compatibility. Delegation with ! is possible. |
| __Ret<T, E> | When you want to handle complex error information in a type-safe manner. | Most robust. The state returned by the function is clear. |
!) allows you to write "Happy Path" processing into the main line,
hiding exception handling behind the scenes. This dramatically improves the visibility of complex business
logic.