Renderingen-US

Errors and catching

Faber does not throw errors the way most languages do. A failure travels back through a dedicated error channel, declared in the signature and separate from the return value. That one decision shapes everything on this page.

The error channel#

declares what a function returns. declares what it may fail with.

reader locale
faber format --locale en — English reader surface
fn divide(int a, int b)  intstring {
    if b  0 {
        throw "division by zero"
    }
    return a / b
}
faber format --locale la — canonical Faber
functio divide(numerus a, numerus b)  numerustextus {
    si b  0 {
        iace "division by zero"
    }
    redde a / b
}
faber format --locale th-TH — Thai
ฟังก์ชัน divide(จำนวน a, จำนวน b)  จำนวนข้อความ {
    ถ้า b  0 {
        โยน "division by zero"
    }
    คืน a / b
}
faber format --locale zh-Hans — Simplified Chinese
函数 divide(整数 a, 整数 b)  整数文本 {
    如果 b  0 {
        抛错 "division by zero"
    }
    返回 a / b
}
faber format --locale zh-Hant — Traditional Chinese
函式 divide(整數 a, 整數 b)  整數文字 {
     b  0 {
        拋出 "division by zero"
    }
    傳回 a / b
}
faber format --locale vi — Vietnamese
hàm divide(số a, số b)  sốvăn_bản {
    nếu b  0 {
        ném "division by zero"
    }
    trả a / b
}
faber format --locale ar — Arabic
دالة divide(عدد a, عدد b)  عددنص {
    إذا b  0 {
        ارم "division by zero"
    }
    أعد a / b
}
faber format --locale hi — Hindi
फलन divide(संख्या a, संख्या b)  संख्यापाठ {
    यदि b  0 {
        इधरफेंको "division by zero"
    }
    लौटाओ a / b
}

Read it as: returns a number, or fails with a textus. The two channels are independent — the success type is not widened, wrapped, or made optional to accommodate failure. A caller reading the signature knows both shapes before looking at the body.

iace sends a value down the error channel. It is not return: it exits by the other route.

Catching#

catch binds whatever came down the error channel.

reader locale
faber format --locale en — English reader surface
fn divide(int a, int b)  intstring {
    if b  0 {
        throw "division by zero"
    }
    return a / b
}

fn tutum(int a, int b)  int {
    do {
        return divide(a, b)
    }
    catch err {
        warn err
        return 0
    }
}

main {
    print tutum(10, 2)
    print tutum(10, 0)
}
faber format --locale la — canonical Faber
functio divide(numerus a, numerus b)  numerustextus {
    si b  0 {
        iace "division by zero"
    }
    redde a / b
}

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

incipit {
    nota tutum(10, 2)
    nota tutum(10, 0)
}
faber format --locale th-TH — Thai
ฟังก์ชัน divide(จำนวน a, จำนวน b)  จำนวนข้อความ {
    ถ้า b  0 {
        โยน "division by zero"
    }
    คืน a / b
}

ฟังก์ชัน tutum(จำนวน a, จำนวน b)  จำนวน {
    ทำ {
        คืน divide(a, b)
    }
    จับ err {
        เตือน err
        คืน 0
    }
}

เริ่ม {
    บันทึก tutum(10, 2)
    บันทึก tutum(10, 0)
}
faber format --locale zh-Hans — Simplified Chinese
函数 divide(整数 a, 整数 b)  整数文本 {
    如果 b  0 {
        抛错 "division by zero"
    }
    返回 a / b
}

函数 tutum(整数 a, 整数 b)  整数 {
    执行 {
        返回 divide(a, b)
    }
    捕获 err {
        警告 err
        返回 0
    }
}

入口 {
    显示 tutum(10, 2)
    显示 tutum(10, 0)
}
faber format --locale zh-Hant — Traditional Chinese
函式 divide(整數 a, 整數 b)  整數文字 {
     b  0 {
        拋出 "division by zero"
    }
    傳回 a / b
}

函式 tutum(整數 a, 整數 b)  整數 {
    執行 {
        傳回 divide(a, b)
    }
    捕捉 err {
        警告 err
        傳回 0
    }
}

入口 {
    註記 tutum(10, 2)
    註記 tutum(10, 0)
}
faber format --locale vi — Vietnamese
hàm divide(số a, số b)  sốvăn_bản {
    nếu b  0 {
        ném "division by zero"
    }
    trả a / b
}

hàm tutum(số a, số b)  số {
    làm {
        trả divide(a, b)
    }
    bắt err {
        cảnh_báo err
        trả 0
    }
}

bắt_đầu {
    ghi_chú tutum(10, 2)
    ghi_chú tutum(10, 0)
}
faber format --locale ar — Arabic
دالة divide(عدد a, عدد b)  عددنص {
    إذا b  0 {
        ارم "division by zero"
    }
    أعد a / b
}

دالة tutum(عدد a, عدد b)  عدد {
    افعل {
        أعد divide(a, b)
    }
    التقط err {
        نبه err
        أعد 0
    }
}

بداية {
    اعرض tutum(10, 2)
    اعرض tutum(10, 0)
}
faber format --locale hi — Hindi
फलन divide(संख्या a, संख्या b)  संख्यापाठ {
    यदि b  0 {
        इधरफेंको "division by zero"
    }
    लौटाओ a / b
}

फलन tutum(संख्या a, संख्या b)  संख्या {
    करो {
        लौटाओ divide(a, b)
    }
    पकड़ो err {
        चेताओ err
        लौटाओ 0
    }
}

आरंभ {
    दिखाओ tutum(10, 2)
    दिखाओ tutum(10, 0)
}

tutum has no in its signature, and that is the point: it handles the failure, so it cannot itself fail. The channel stops here.

catch attaches to more than do#

This is the part that surprises people arriving from other languages. catch is not the tail of a try statement — it attaches to structured statements generally. A loop can carry its own handler:

reader locale
faber format --locale en — English reader surface
main {
    const list<string> raw  ["1", "two", "3"]
    do {
        for from raw const item {
            const int n  item ↦ int
            print n
        }
    }
    catch err {
        warn err
    }
}
faber format --locale la — canonical Faber
incipit {
    fixum lista<textus> raw  ["1", "two", "3"]
    fac {
        itera ex raw fixum item {
            fixum numerus n  item ↦ numerus
            nota n
        }
    }
    cape err {
        mone err
    }
}
faber format --locale th-TH — Thai
เริ่ม {
    คงที่ รายการ<ข้อความ> raw  ["1", "two", "3"]
    ทำ {
        วน ออก raw คงที่ item {
            คงที่ จำนวน n  item ↦ จำนวน
            บันทึก n
        }
    }
    จับ err {
        เตือน err
    }
}
faber format --locale zh-Hans — Simplified Chinese
入口 {
    常量 列表<文本> raw  ["1", "two", "3"]
    执行 {
        遍历 取自 raw 常量 item {
            常量 整数 n  item ↦ 整数
            显示 n
        }
    }
    捕获 err {
        警告 err
    }
}
faber format --locale zh-Hant — Traditional Chinese
入口 {
    定值 列表<文字> raw  ["1", "two", "3"]
    執行 {
        遍歷 取自 raw 定值 item {
            定值 整數 n  item ↦ 整數
            註記 n
        }
    }
    捕捉 err {
        警告 err
    }
}
faber format --locale vi — Vietnamese
bắt_đầu {
    hằng danh_sách<văn_bản> raw  ["1", "two", "3"]
    làm {
        lặp từ raw hằng item {
            hằng số n  item ↦ số
            ghi_chú n
        }
    }
    bắt err {
        cảnh_báo err
    }
}
faber format --locale ar — Arabic
بداية {
    ثابت قائمة<نص> raw  ["1", "two", "3"]
    افعل {
        كرر من raw ثابت item {
            ثابت عدد n  item ↦ عدد
            اعرض n
        }
    }
    التقط err {
        نبه err
    }
}
faber format --locale hi — Hindi
आरंभ {
    स्थिर सूची<पाठ> raw  ["1", "two", "3"]
    करो {
        दोहराओ सेवन raw स्थिर item {
            स्थिर संख्या n  item ↦ संख्या
            दिखाओ n
        }
    }
    पकड़ो err {
        चेताओ err
    }
}

And so can a while loop:

reader locale
faber format --locale en — English reader surface
main {
    var int i  0
    do {
        while i ≺ 3 {
            i  i + 1
            if i  2 {
                throw "halfway"
            }
        }
    }
    catch err {
        warn err
    }
}
faber format --locale la — canonical Faber
incipit {
    varia numerus i  0
    fac {
        dum i ≺ 3 {
            i  i + 1
            si i  2 {
                iace "halfway"
            }
        }
    }
    cape err {
        mone err
    }
}
faber format --locale th-TH — Thai
เริ่ม {
    แปร จำนวน i  0
    ทำ {
        ขณะ i ≺ 3 {
            i  i + 1
            ถ้า i  2 {
                โยน "halfway"
            }
        }
    }
    จับ err {
        เตือน err
    }
}
faber format --locale zh-Hans — Simplified Chinese
入口 {
    变量 整数 i  0
    执行 {
         i ≺ 3 {
            i  i + 1
            如果 i  2 {
                抛错 "halfway"
            }
        }
    }
    捕获 err {
        警告 err
    }
}
faber format --locale zh-Hant — Traditional Chinese
入口 {
    變值 整數 i  0
    執行 {
         i ≺ 3 {
            i  i + 1
             i  2 {
                拋出 "halfway"
            }
        }
    }
    捕捉 err {
        警告 err
    }
}
faber format --locale vi — Vietnamese
bắt_đầu {
    biến số i  0
    làm {
        trong_khi i ≺ 3 {
            i  i + 1
            nếu i  2 {
                ném "halfway"
            }
        }
    }
    bắt err {
        cảnh_báo err
    }
}
faber format --locale ar — Arabic
بداية {
    متغير عدد i  0
    افعل {
        طالما i ≺ 3 {
            i  i + 1
            إذا i  2 {
                ارم "halfway"
            }
        }
    }
    التقط err {
        نبه err
    }
}
faber format --locale hi — Hindi
आरंभ {
    चर संख्या i  0
    करो {
        जबतक i ≺ 3 {
            i  i + 1
            यदि i  2 {
                इधरफेंको "halfway"
            }
        }
    }
    पकड़ो err {
        चेताओ err
    }
}

The handler belongs to the construct it follows. There is no separate try keyword to wrap things in — do is simply the bare block form for when you want a handler and have no other statement to hang it on.

Failing without a message#

A function that declares and does not catch propagates automatically — callers must deal with it or declare their own channel.

reader locale
faber format --locale en — English reader surface
fn parse(string raw)  intstring {
    if raw  "" {
        throw "empty input"
    }
    return raw ↦ int0
}

fn duplum(string raw)  intstring {
    return parse(raw) * 2
}

main {
    do {
        print duplum("21")
    }
    catch err {
        warn err
    }
}
faber format --locale la — canonical Faber
functio parse(textus raw)  numerustextus {
    si raw  "" {
        iace "empty input"
    }
    redde raw ↦ numerus0
}

functio duplum(textus raw)  numerustextus {
    redde parse(raw) * 2
}

incipit {
    fac {
        nota duplum("21")
    }
    cape err {
        mone err
    }
}
faber format --locale th-TH — Thai
ฟังก์ชัน parse(ข้อความ raw)  จำนวนข้อความ {
    ถ้า raw  "" {
        โยน "empty input"
    }
    คืน raw ↦ จำนวน0
}

ฟังก์ชัน duplum(ข้อความ raw)  จำนวนข้อความ {
    คืน parse(raw) * 2
}

เริ่ม {
    ทำ {
        บันทึก duplum("21")
    }
    จับ err {
        เตือน err
    }
}
faber format --locale zh-Hans — Simplified Chinese
函数 parse(文本 raw)  整数文本 {
    如果 raw  "" {
        抛错 "empty input"
    }
    返回 raw ↦ 整数0
}

函数 duplum(文本 raw)  整数文本 {
    返回 parse(raw) * 2
}

入口 {
    执行 {
        显示 duplum("21")
    }
    捕获 err {
        警告 err
    }
}
faber format --locale zh-Hant — Traditional Chinese
函式 parse(文字 raw)  整數文字 {
     raw  "" {
        拋出 "empty input"
    }
    傳回 raw ↦ 整數0
}

函式 duplum(文字 raw)  整數文字 {
    傳回 parse(raw) * 2
}

入口 {
    執行 {
        註記 duplum("21")
    }
    捕捉 err {
        警告 err
    }
}
faber format --locale vi — Vietnamese
hàm parse(văn_bản raw)  sốvăn_bản {
    nếu raw  "" {
        ném "empty input"
    }
    trả raw ↦ số0
}

hàm duplum(văn_bản raw)  sốvăn_bản {
    trả parse(raw) * 2
}

bắt_đầu {
    làm {
        ghi_chú duplum("21")
    }
    bắt err {
        cảnh_báo err
    }
}
faber format --locale ar — Arabic
دالة parse(نص raw)  عددنص {
    إذا raw  "" {
        ارم "empty input"
    }
    أعد raw ↦ عدد0
}

دالة duplum(نص raw)  عددنص {
    أعد parse(raw) * 2
}

بداية {
    افعل {
        اعرض duplum("21")
    }
    التقط err {
        نبه err
    }
}
faber format --locale hi — Hindi
फलन parse(पाठ raw)  संख्यापाठ {
    यदि raw  "" {
        इधरफेंको "empty input"
    }
    लौटाओ raw ↦ संख्या0
}

फलन duplum(पाठ raw)  संख्यापाठ {
    लौटाओ parse(raw) * 2
}

आरंभ {
    करो {
        दिखाओ duplum("21")
    }
    पकड़ो err {
        चेताओ err
    }
}

duplum never mentions failure in its body. It declares the channel and lets parse's failure travel through.

Errors as a parameter#

errata marks a parameter that carries an error value, for functions written to receive one rather than produce it.

reader locale
faber format --locale en — English reader surface
fn logga(string context)  void {
    warn context
}
faber format --locale la — canonical Faber
functio logga(textus context)  vacuum {
    mone context
}
faber format --locale th-TH — Thai
ฟังก์ชัน logga(ข้อความ context)  เปล่า {
    เตือน context
}
faber format --locale zh-Hans — Simplified Chinese
函数 logga(文本 context)  无值 {
    警告 context
}
faber format --locale zh-Hant — Traditional Chinese
函式 logga(文字 context)  空值 {
    警告 context
}
faber format --locale vi — Vietnamese
hàm logga(văn_bản context)  trống {
    cảnh_báo context
}
faber format --locale ar — Arabic
دالة logga(نص context)  فراغ {
    نبه context
}
faber format --locale hi — Hindi
फलन logga(पाठ context)  रिक्त {
    चेताओ context
}

Related: Testing · Conversions for in its other role, as conversion recovery · Errors and testing for the full treatment.