This is wrong, this is not catch/3. catch/3 is not
able to catch events in the continuation. It can
only catch exceptions occuring in G, but not in H:
catch(G, _, _), H
The catch "block", is the goals in G, and every
subgoal that is created during solving G. And throw
statement or thread interruption in G is catched.
The goals in H cannot be catched by the above
catch/3 control construct. Since any throw in
H is outside of the scope of the catch "block".
So the behaviour is:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- catch(write(1),tag(E),(write(E),write(end))), throw(tag(2)).
1
ERROR: Unhandled exception: tag(2)
Means the throw(tag(2)) permeates to the toplevel, and
is not catched by the catch/3 control construct in the
query. This is seen by the "Unhandled..." message.
What is this term "events in the continuation" I am using
for when something happens in H and not G. Well this
is terminology from setup_call_clean/3.
You find the following classification of events:
== event in the catch block ==
exception(Exception)
Goal raised the given exception.
== event in the continuation ==
external_exception(Exception)
Goal succeeded and it is now discarded due to an exception.
The ISO catch/3 is supposed to only catch events in the
catch block but not events in the continuation. On the other
hand the setup_call_cleanup/3 would execute the cleanup also
for when there is an event in the continuation. There is
no ISO definition for setup_call_cleanup/3 , but a
relatively good draft for it:
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/cleanup