Heroes / Esempi / 03-fallible

examples/gallery/03-fallible.hero

Gli errori sono valori con un tipo: Heroes non usa null o eccezioni.

T? contiene un valore di tipo T oppure un errore. fail crea l’errore, ? lo restituisce alla funzione chiamante e match distingue i due casi. Il tipo rende esplicita la possibilità di un errore.

Eseguilo

$ heroes run examples/gallery/03-fallible.hero

Questo esempio serve a illustrare il linguaggio. Qui trovi il programma e non un risultato: non ci sono ancora test che confrontino il suo output byte per byte.

Il programma

## Failure is a value
#
# There is no `null` and there are no exceptions. A `T?` is a `T` or an
# error, `fail` makes one, `?` hands it to the caller, and `match` is the
# general way to look.

# Parses a decimal digit. Fails on anything else.
function digit_of(c: u8) -> i64?
    if c < '0' || c > '9'
        return fail(code: "not_a_digit", msg: "expected 0-9")
    return ok(to_i64(c - '0').must())

# Reads a whole non-negative number. Empty input is an error, not a zero.
function number_of(text: str) -> i64?
    if text.len() == 0
        return fail(code: "empty", msg: "there is nothing to read")
    total: i64 @= 0

    for i in range(from: 0, to: text.len())
        total @ total * 10 + digit_of(text[i])?

    return ok(total)

# The `?` above is the whole point: three lines, no error handling in sight,
# and the first bad character stops everything.
function average_of(parts: [str]) -> i64?
    sum: i64 @= 0

    for p in parts
        sum @ sum + number_of(p)?

    if parts.len() == 0
        return fail(code: "empty", msg: "no parts to average")
    return ok(sum / parts.len())

# Four ways to read a fallible value, in the order you reach for them.
function report(text: str) -> str
    match number_of(text)
        .ok v  => return "read " + v.to_str()
        .err e => return "failed: " + e.code + " (" + e.msg + ")"

function first_or_zero(parts: [str]) -> i64
    return number_of(parts[0]).default(0)

test "a good number and a bad one"
    assert number_of("120").must() == 120
    assert number_of("12x").is_err()
    assert report("7") == "read 7"
    assert first_or_zero(["oops"]) == 0

function main()
    print(report("42"))
    print(report("4b2"))
    print(average_of(["10", "20", "30"]).default(-1))
examples/gallery/03-fallible.hero, 54 righe

impronta sha256 24f91adb4042 · 1 file · index.json

Successivo: 04-loops. Tutti gli esempi. ← Precedente: 02-tokens

Eseguine uno: i quattro comandi. Impara il linguaggio, oppure leggi la specifica completa in un solo file.