[ Control | Reference Manual | Alphabetic Index ]

catch(+Goal, ?Catcher, +Recovery)

Equivalent to call(Goal) if Goal succeeds or fails. If Goal throws an exception that unifies with Catcher, Recovery is executed
Goal
A callable term.
Catcher
Any term.
Recovery
A callable term.

Description

First, Goal is called from the current module, and if this succeeds then catch/3 succeeds. If Goal fails, then so does the call of catch/3. In other words, unless exceptions are involved, catch(Goal, ..., ...) operates like call(Goal), and Catcher and Recovery are ignored.

If, however, an exception is thrown during the execution of Goal (either by an error condition in a built-in predicate, or by an invocation of throw/1), and the exception term unifies with Catcher, then the execution of Goal is undone, and Recovery is called instead. In this case, catch(Goal,Catcher,Recovery) is equivalent to call(Recovery). Note that exceptions within Recovery are NOT caught by this catch!

If Goal terminates with an exception, and the exception term does NOT unify with Catcher, then the exception is passed on, allowing an ancestor catch/3 to catch it. The innermost invocation of catch/3 whose Catcher argument matches the exception will catch it.

NOTE: block/3 is a deprecated alias for catch/3, and behaves identically. exit_block/1 is a deprecated alias for throw/1, and behaves identically.

Modes and Determinism

Modules

This predicate is sensitive to its module context (tool predicate, see @/2).

Fail Conditions

Fail if Goal fails, or if Goal exits and Recovery fails

Resatisfiable

Resatisfiable if Goal is resatisfiable, or Goal exits and Recovery is resatisfiable

Examples

      % success, failure and backtracking are not affected by the catch:
      ?- catch(X is 3+4, T, writeln(recover(T))).
      X = 7
      T = T
      Yes (0.00s cpu)

      ?- catch(8 is 3+4, T, writeln(recover(T))).
      No (0.00s cpu)

      ?- catch(member(X,[1,2]), T, writeln(recover(T))).
      X = 1
      T = T
      Yes (0.00s cpu, solution 1, maybe more) ? ;
      X = 2
      T = T
      Yes (0.00s cpu, solution 2)


      % A variable Catcher catches all throws
      ?- catch(throw(hello), T, writeln(recover(T))).
      recover(hello)
      T = hello
      Yes (0.00s cpu)


      % An instantiated Catcher catches only matching throws
      ?- catch(throw(hello), hello, writeln(recovered)).
      recovered
      Yes (0.00s cpu)

      ?- catch(throw(hello), world, writeln(recovered)).
      uncaught exception in throw(hello)
      Abort


      % A partially instantiated Catcher catches only matching throws
      ?- catch(throw(hello(world)), hello(Who), writeln(recovered(Who))).
      recovered(world)
      Yes (0.00s cpu)

      ?- catch(throw(hi(world)), hello(Who), writeln(recovered(Who))).
      uncaught exception in throw(hi(world))
      Yes (0.00s cpu)


      % ECLiPSe's error handlers usually execute throw(abort)
      % and therefore can be caught with a catch:
      ?- catch(X is 1//0, T, writeln(recover(T))).
      arithmetic exception in //(1, 0, X)
      recover(abort)
      X = X
      T = abort
      Yes (0.01s cpu)


      % Executing a recovery action AND passing the exception on:
      ?- catch(throw(hello), T, (writeln(caught(T)), throw(T))).
      caught(hello)
      uncaught exception in throw(hello)
      Abort

See Also

throw / 1, abort / 0