Section 8.2

The language's errors, and finally

Catching what the language throws — and guaranteeing a cleanup, whatever happens.

The course has already had you provoke two errors defenceless: the index out of bounds in 6.1, the integer division by zero in 2.3. The language throws them through the very same mechanism as you — archetypes, supplied without an import.

@entry(start)
object MyProgram {
    start() {
        var readings := [12, 19, 7];

        try {
            Console.print(text: $"{readings[5]}");
        } catch (raised: IndexOutOfRangeError) {
            Console.print(text: $"refused: {raised.message}");
        } finally {
            Console.print(text: "the cauldron is rinsed");
        }

        Console.print(text: "the program goes on");
    }
}

The language’s errors are archetypes like yours

IndexOutOfRangeError, DivideByZeroError, OverflowError: each carries a message, and a catch takes them like your own. The 6.1 program that fell on readings[5] now knows how to survive — “the program goes on”.

var doses := 0;
try {
    Console.print(text: $"{10 / doses}");
} catch (raised: DivideByZeroError) {
    Console.print(text: $"caught: {raised.message}");
}

Several catches stack

After one try, the catches are written in a row and tried in writing order — the first whose type matches receives the error, the others see nothing. An error none of them takes keeps climbing.

finally — whatever happens

} finally {
    Console.print(text: "the cauldron is rinsed");
}

The finally block runs in every case: error caught, no error raised, and even an error that keeps climbing. It is where cleanup belongs — closing, rinsing, giving back — the things that must depend on nothing.

One rule applies inside it, and the compiler holds it:

error[D007]: 'return' is forbidden inside a 'finally': it would silently overwrite
what the 'try' returns (see docs/decisions.md, 'Gestion des erreurs')

A return inside a finally would silently overwrite what the try returns — the trap exists elsewhere, Archon closes it.

Your turn

  • Set the index to 1: no error anymore — and “the cauldron is rinsed” still prints. finally does not depend on the error.
  • Replace the array access with 10 / doses where doses is zero, and the catch with DivideByZeroError: the course’s other error, caught the same way.
  • Write a return inside the finally of a method returning an int, and read the refusal.
  • Stack both catches — IndexOutOfRangeError then DivideByZeroError — on a try that can only raise the second: the first sees nothing pass.