Result — Mandatory Error Handling
Overview
Every function in Nitpick returns Result<T> (except extern functions). The compiler
forces you to handle the result — unhandled Results are compile errors. This is the
core of Nitpick's safety model at the function level.
Canonical v0.33.6 handling guide: see
guide/result/for the full operator andcatchcookbook.
Structure
Result<T> = { T:value, ptr:error, i8:is_error }
- Success:
valueis set,erroris NIL,is_erroris false - Error:
valueis the zero/NIL-shaped payload for the type where applicable,errorcarries the failure code internally, andis_erroris true
Source-facing .error / contextual catch error bindings currently expose
the runtime error code as int32.
Creating Results
Inside functions (not main or failsafe):
func:divide = flt64(int32:a, int32:b) {
if (b == 0) {
fail 1; // return error Result
}
pass (a / b); // return success Result
};
pass value— return success, wraps value in Resultfail errcode— return error, wraps the runtime error code in Result- Both support paren syntax:
pass(value),fail(errcode)
Handling Results
// Safe unwrap with fallback
flt64:val = divide(10, 3) ? 0.0;
// Null coalesce is for Optional/pointers, not Result errors
flt64:val = optional_value ?? default_value;
// Emphatic Result fallback unwrap
flt64:val = divide(10, 3) ?! 0.0;
// Defaults keyword — scoped fallback for chains
flt64:val = a() + b() + c() defaults 0.0;
// Shorthand: flt64:val = a() + b() + c() ?| 0.0;
// Drop (discard result entirely)
drop divide(10, 3);
// Shorthand: _? divide(10, 3);
// Raw (extract value, ignore error)
flt64:val = raw divide(10, 3);
// Shorthand: flt64:val = _! divide(10, 3);
// Error-aware fallback
flt64:val = divide(10, 0) catch (err) { 0.0 };
// Discard assignment
_ = divide(10, 3);
Operator Summary
| Operator | Keyword | Meaning |
|---|---|---|
? |
— | Safe unwrap with fallback value |
?? |
— | Optional/pointer null coalesce |
?! |
— | Emphatic Result fallback unwrap |
?\| |
defaults |
Scoped fallback for expression chains |
_? |
drop |
Discard Result entirely |
_! |
raw |
Extract value, bypass error checking |
| contextual | catch |
Error-aware Result fallback |
rawvsnodrop—rawis a Result-system unwrap (Result<T>→T).nodropis a RAII-system opt-out (v0.31.6.x, W-04) that suppresses the auto-dropthe IR generator inserts for managed regions. They are orthogonal and compose; see guide/drop/surface.md.
Auto-Unwrap in Argument Position
When passing a Result
func:add = int32(int32:a, int32:b) { pass (a + b); };
func:get_val = int32() { pass 42; };
// get_val() returns Result<int32>, but add() expects int32
// Result auto-unwraps in argument position
int32:sum = raw add(get_val(), get_val());
This does not apply to variable assignment — you must explicitly unwrap.
The ok Keyword
ok allows passing a variable whose value may be unknown:
ok maybe_unknown_value;
main and failsafe
main and failsafe are special — they use exit instead of pass/fail:
func:main = int32() {
exit 0; // exit program with code 0
};
func:failsafe = int32(tbb32:err) {
exit 1; // must exit with code > 0
};
Related
- tbb.md — TBB error propagation (value-level)
- result/ — canonical Result handling cookbook
- functions/main_failsafe.md — mandatory functions
- functions/result_system.md — pass/fail patterns