[ 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

- catch(+, +, +)
- catch(+, -, +)

### 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