Exceptions & Error Handling

Errors have the form error(Formal, Context):

21.1 catch/3 and throw/1

safe_divide(X, Y, R) :-
    catch(R is X / Y,
          error(evaluation_error(zero_divisor), _),
          ( format("Division by zero!~n"), R = undefined )).

?- catch(throw(my_error(42)), my_error(Code), format("caught ~w~n", [Code])).
?- catch(atom_length(X, L), E, (print_message(error, E), fail)).

21.2 ISO error terms

Errors have the form error(Formal, Context):

argument not sufficiently instantiated type_error(Type, Culprit) wrong type (atom_length(1, L) in strict mode) domain_error(Domain, Culprit) right type, invalid value existence_error(procedure, PI) existence_error(source_sink, File)

permission_error(Action, Type, Culprit) e.g. modify static procedure zero_divisor, undefined out of memory/stack

21.3 Throwing standard errors

:- use_module(library(error)).
check_age(A) :-
    must_be(nonneg, A),                        % throws type/instantiation errors
    ( A > 150 -> domain_error(realistic_age, A) ; true ).

type_error(integer, foo), existence_error(user, bob), instantiation_error(X).
is_of_type(positive_integer, 5).

21.4 Cleanup: setup_call_cleanup/3

Cleanup runs whether the goal succeeds deterministically, fails, raises, or is cut.

setup_call_cleanup(open(F, read, S), process(S), close(S)).

21.5 Unknown predicates

:- set_prolog_flag(unknown, fail).    % default is error (recommended)