If the exception is not caught by any catch/3 in the user program, then
The term that is unified with the ancestor's Catcher is a copy of the Ball, i.e. if it contains variables, these are not identical to the original ones in Ball.
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.
% 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) % The caught term is a copy of the thrown term (fresh variables) ?- T1=f(X), catch(throw(T1), T2, true), variant(T1, T2), T1\==T2. T1 = f(X_88) T2 = f(X_510) Yes (0.00s cpu) Error: throw(_). (Error 4). throw(never_caught). (Error 230).