4.11 Exception Handling
It is sometimes necessary to exit prematurely from an executing
procedure, for example because some situation was detected which
makes continuing impossible.
In this situation, one wants to return to some defined state and
perform some kind of recovery action.
This functionality is provided by block/3 and exit_block/1.
By wrapping a predicate call into block/3, any irregular termination
can be caught and handled, e.g.
block(Goal, BTag, Recovery)
like call(Goal), except that in addition a Recovery goal is set up, which
can be called by exit_block from anywhere inside the
call to Goal. When exit_block(ETag) is called, then if ETag
unifies with a BTag from an enclosing block, the
recovery goal associated with that block is called, with the system
immediately failing back to where the block was called. In
addition, ETag can be used to pass information to the recovery
goal, if BTag occurs as an argument of Recovery.
will transfer control to the innermost enclosing block/3 whose
BTag argument unifies with ETag.
Figure 4.6: Exception Handling
When built-in predicates raise errors, this results in the predicate
being exited with the tag
printf("Execution of main/3 aborted with %w%n", [Problem])
( test(...) -> ... ; exit_block(test_failed) ),
abort, which can also be caught:
Note that timeouts and stack overflows also lead to exits and can be
caught this way.
?- block(X is 1//0, T, true).
arithmetic exception in //(1, 0, X)
X = X
T = abort
Yes (0.00s cpu)