SWI-Prolog defines the predicates catch/3 and throw/1 for ISO compliant raising and catching of exceptions. In the current implementation (2.9.0), only part of the built-in predicates generate exceptions. In general, exceptions are implemented for I/O and arithmetic.
The overhead of calling a goal through catch/3 is very comparable to call/1. Recovery from an exception has a similar overhead.
If there is no catch/3 willing to catch the error in the current Prolog context, the toplevel (prolog/0) catches the error and prints a warning message. If an exception was raised in a callback from C (see chapter 5), PL_next_solution() will fail and the exception context can be retrieved using PL_exception().
the introduction of exceptions in SWI-Prolog a runtime error was handled
by printing an error message, after which the predicate failed. If the
prolog_flag (see current_prolog_flag/2)
was in effect (default), the tracer was switched on. The combination of
the error message and trace information is generally sufficient to
locate the error.
With exception handling, things are different. A programmer may wish to trap an exception using catch/3 to avoid it reaching the user. If the exception is not handled by user-code, the interactive toplevel will trap it to prevent termination.
If we do not take special precautions, the context information associated with an unexpected exception (i.e. a programming error) is lost. Therefore, if an exception is raised, which is not caught using catch/3 and the toplevel is running, the error will be printed, and the system will enter trace mode.
If the system is in an non-interactive callback from foreign code and there is no catch/3 active in the current context, it cannot determine whether or not the exception will be caught by the external routine calling Prolog. It will then base its behaviour on the prolog_flag debug_on_error:
While looking for the context in which an exception takes place, it is adviced to switch on debug mode using the predicate debug/0.
Builtin predicates generates exceptions using a term
error(Formal, Context). The first argument is the `formal'
description of the error, specifying the class and generic defined
context information. When applicable, the ISO error-term definition is
used. The second part describes some additional context to help the
programmer while debugging. In its most generic form this is a term of
context(Name/Arity, Message), where
Name/Arity describes the built-in predicate that
raised the error, and Message provides an additional
description of the error. Any part of this structure may be a variable
if no information was present.
The predicate print_message/2 may be used to print a message term in a human readable format. The other predicates from this section allow the user to refine and extend the message system. The most common usage of print_message/2 is to print error messages from exceptions. The code below prints errors encountered during the execution of Goal, without further propagating the exception and without starting the debugger.
..., catch(Goal, E, ( print_message(error, E), fail )), ...
Another common use is to defined message_hook/3 for printing messages that are normally silent, suppressing messages, redirecting messages or make something happen in addition to printing the message.
silent. A human-readable message is printed to the stream
This predicate first translates the Term into a list of `message lines' (see print_message_lines/3 for details). Next it will call the hook message_hook/3 to allow the user intercepting the message. If message_hook/3 fails it will print the message unless Kind is silent.
predicate and its rules are in the file
<plhome>/boot/messages.pl, which may be
inspected for more information on the error messages and related error
See also message_to_string/2.
format(Stream, Format, ).
See also print_message/2 and message_hook/3.
userto intercept messages from print_message/2. Term and Kind are the same as passed to print_message/2. Lines is a list of format statements as described with print_message_lines/3. See also message_to_string/2.
This predicate should be defined dynamic and multifile to allow other modules defining clauses for it too.