---
{
"@context": "https://nxdlang.org/schema",
"doc_id": "TE006",
"title": "",
"description": "",
"layer": "Examples",
"category": "Tiny Examples",
"keywords": [],
"doc_version": "1.0",
"status": "active"
}
---
# TE006 — Error Handling (Tiny Layer)
## Problem Statement
Demonstrate NXD’s structured error‑handling model:
- `TRY / CATCH` for exception‑style handling
- `RESULT` union type for recoverable errors
- `RAISE` for structured diagnostics
- Pattern matching on `RESULT`
- No implicit conversions between `ERR` and `OK`
This example shows a safe integer parser that returns `RESULT`, and a caller that handles both exceptions and recoverable errors.
---
# Canonical NXD (≤30 lines)
```nxd
MODULE demo.error
TYPE RESULT UNION { OK(any), ERR(string) }
FUNC PARSE_INT(S):
IF S IS string:
IF S CONTAINS NON_DIGIT:
RETURN ERR("not numeric")
RETURN OK(S AS int)
RAISE E5002 # invalid cast
FUNC MAIN():
LET R SET PARSE_INT("42")
MATCH R:
CASE OK(V):
PRINTLN(V)
CASE ERR(E):
PRINTLN("error: " ADD E)
LET OUT SET TRY PARSE_INT("hello") CATCH E:
RETURN ERR("exception: " ADD E)
PRINTLN(OUT)
RETURN none
```
---
# Semantic Notes
- `RESULT` is a tagged union with `OK` and `ERR`.
- `PARSE_INT` returns `ERR` for non‑numeric strings.
- `S AS int` uses explicit casting rules (may fail).
- `RAISE E5002` triggers a structured diagnostic.
- `MATCH` must be exhaustive for sum types.
- `TRY/CATCH` handles exceptions, not `ERR` values.
- No implicit conversion between `ERR` and exceptions.
- Evaluation order is strictly left‑to‑right.
---
# Backend Outputs
### Nim
```nim
type Result[T] = object
ok: bool
val: T
err: string
proc parseInt(s: string): Result[int] =
if not s.allCharsInSet({'0'..'9'}):
return Result[int](ok: false, err: "not numeric")
try:
return Result[int](ok: true, val: parseInt(s))
except:
raise newException(ValueError, "E5002")
proc main() =
let r = parseInt("42")
if r.ok:
echo r.val
else:
echo "error: ", r.err
var out: Result[int]
try:
out = parseInt("hello")
except ValueError:
out = Result[int](ok: false, err: "exception")
echo out
```
---
### Elixir
```elixir
defmodule Demo.Error do
def parse_int(s) when is_binary(s) do
if String.match?(s, ~r/^\d+$/) do
{:ok, String.to_integer(s)}
else
{:error, "not numeric"}
end
end
def parse_int(_), do: raise "E5002"
def main() do
r = parse_int("42")
case r do
{:ok, v} -> IO.puts(v)
{:error, e} -> IO.puts("error: " <> e)
end
out =
try do
parse_int("hello")
rescue
_ -> {:error, "exception"}
end
IO.inspect(out)
end
end
```
---
### D
```d
module demo.error;
import std.stdio;
import std.conv;
struct Result(T) {
bool ok;
T val;
string err;
}
Result!int parseInt(string s) {
import std.regex;
if (!match(s, regex(`^\d+$`)))
return Result!int(false, 0, "not numeric");
try {
return Result!int(true, to!int(s), "");
} catch (Exception e) {
throw new Exception("E5002");
}
}
void main() {
auto r = parseInt("42");
if (r.ok)
writeln(r.val);
else
writeln("error: ", r.err);
Result!int out;
try {
out = parseInt("hello");
} catch (Exception e) {
out = Result!int(false, 0, "exception");
}
writeln(out);
}
```
---
# Audit Rules
- `RESULT` must be pattern‑matched exhaustively.
- `TRY/CATCH` must not swallow `ERR` values.
- `RAISE` must produce structured diagnostics (`E5002`).
- No implicit conversions allowed between exceptions and `ERR`.
- Backend lowering must preserve sum‑type semantics.
Documentation