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)