catch/3

Module: builtins

catch/3 — execute a goal, specifying an exception handler
throw/1 — give control to an exception handler

ISO Standard Predicate

FORMS

catch(Goal, Pattern, ExceptionGoal)

throw(Reason)

DESCRIPTION

catch/3 provides a facility for catching errors or exceptions and handling them gracefully. Execution of catch/3 will cause the goal Goal to be executed. If no errors or throws occur during the execution of Goal, then catch/3 behaves just as if call/1 were called with Goal. Goal may succeed thus giving control to portions of the program outside the scope of the catch. Failures in these portions of the program may cause re-execution (via backtracking) of goals in the scope of the catch of which Goal is the ancestor.

If a goal of the form throw(Reason) is encountered during the execution of Goal or in any subsequent re-execution of Goal, then the goal ExceptionGoal of the catch with the innermost scope capable of unifying Reason and Pattern together will be executed with this unification intact. Once started, the execution of the goal ExceptionGoal behaves just like the execution of any other goal. The goal ExceptionGoal is outside of the scope of the catch which initiated the execution of ExceptionGoal, so any throws encountered during the execution of ExceptionGoal will be handled by catches which are ancestors of the catch which initiated the execution of ExceptionGoal. This means that a handler may catch some fairly general pattern, deal with some aspects which it is prepared for, but throw on back to some earlier handler for those aspects for which it is not prepared.

Many of the builtins will cause an error if the types of the arguments to the builtin are wrong. There are other reasons for errors such as exhausting a certain resource. Whatever the cause, an error occurring during the execution of a goal causes throw/1 to be executed. The effect is as if the goal which caused the error where replaced by a goal throw(error(ErrorTerm, ErrorInfo)) where ErrorTerm and ErrorInfo supply information about the error. ErrorTerm is mandated by ISO Prolog Standard. ErrorInfo is an implementation defined (and therefore specific) term which may or may not provide additional information about the error.

The ISO Prolog Standard specifies that ErrorTerm be one of the following forms:

In ALS Prolog, ErrorInfo is a list providing additional information where the ISO Prolog Standard mandated term ErrorTerm falls short. The terms which may be on this list take the following forms:

EXAMPLES

Attempt to open a non-existent file.

?- open(wombat,read,S).
Error: Operation attempted on object of type source_sink which does not exist.
Operation attempted on: wombat.
- Goal:          sio:open(wombat,read,_A,?)
- Throw pattern: error(existence_error(source_sink,wombat),
                     [sio:open(wombat,read,_A,?)])

Attempt to open a file when the file argument is an uninstantiated variable:

?- open(_, read, S).
Error: Instantiation error.
- Goal:          sio:open(_A,read,_B,[type(text)])
- Throw pattern: error(instantiation_error,[sio:open(_A,read,_B,*)])

Define a procedure integer_list/2 to illustrate a use of throw/1. Note that il/2 builds the list and throws the result back at the appropriate time.

?- reconsult(user).
integer_list(N,List)
    :-
    catch(il(N,[]),int_list(List),true),
    !.

il(0,L)
    :-
    throw(int_list(L)).
il(N,L)
    :-
    NN is N-1,
    il(NN,[N|L]).
^D
?- integer_list(8,L).
L=[1,2,3,4,5,6,7,8]
yes.

ERRORS

Goal is a variable

—- > instantiation_error.

Goal is not a callable term

—- > type_error(callable, Goal). [not yet implemented ]

Reason does not unify with Pattern in any call of catch/3

—- > system_error. [not yet implemented ]

NOTES

In the present implementation of ALS Prolog, catch/3 leaves a choice point which is used to restore the scope of the catch when backtracked into. This choice point remains around even for determinate goals which are called from catch. Thus when catch succeeds, you should assume that a choice point has been created. If the program should be determinate, a cut should be placed immediately after the catch. It is expected that at some point in the future, this unfortunate aspect of ALS Prolog will be fixed, thus obviating the need for an explicit cut.

If throw/1 is called with Reason instantiated to a pattern which does not match Pattern in any call of catch/3, control will return to the program which started the Prolog environment. This usually means that Prolog silently exits to an operating system shell. When using the development environment, however, the Prolog shell establishes a handler for catching uncaught throws or errors thus avoiding this unceremonious exit from the Prolog system. It is occassionally possible, particularly with resource errors, to end up in this last chance handler only to have another error occur in attempting to handle the error. Since no handler exists to handle this error, control returns to the operating system often with no indication of what went wrong.