
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

Arguments
   Goal                A callable term.
   Catcher             Any term.
   Recovery            A callable term.

Type
   Control

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
