Renderingla

Error handling

Faber separates three related ideas that many languages collapse into one shape:

ConstructMeaning
→ TNormal success return channel
T ∪ nihilAbsence in the success value domain
⇥ ERecoverable alternate-exit channel for errors

Normal return

functio porta(numerus x) → numerus {
    si x < 0 ∴ redde 0
    redde x * 2
}

Failable functions

Use when a function can leave by an error channel:

functio divide(numerus a, numerus b) → numerus ⇥ textus {
    si b ≡ 0 ∴ iace "division by zero"
    redde a / b
}

Throwing — iace

iace sends a value on the error channel:

functio exigePositivum(numerus value) ⇥ textus {
    si value < 0 ∴ iace "negative value"
}

Recovery — fac / cape

Callers recover locally with a fac block and a cape handler:

functio divide(numerus a, numerus b) → numerus {
    si b ≡ 0 {
        redde 0
    }
    redde a / b
}

functio tutum(numerus a, numerus b) → numerus {
    fac {
        redde divide(a, b)
    }
    cape err {
        mone err
        redde 0
    }
}

A direct failable call is not an ordinary expression. Place calls to → T ⇥ E functions inside an active fac / cape boundary.

Inline conversion recovery

can also specify an inline recovery value on conversions:

fixum textus raw ← "42"
fixum _ n ← raw ↦ numerus ⇥ 0

Effect-only failable

For functions that error but do not return a success value, omit → T:

functio exigePositivum(numerus value) ⇥ textus {
    si value < 0 ∴ iace "negative value"
}

Current status

, redde, , iace, and fac / cape are live grammar and checker surfaces. Rust and Go lowering for full / iace / cape runtime behaviour is still a backend gap — these pass type-checking but do not yet emit failable runtime code to all targets.