🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.prolog
Article #2337

Re: block and exit_block

#2337
From: Richard A. O'Keefe
Date: Wed, 19 Jun 1991 10:21
100 lines
4704 bytes
In article <1991Jun18.125519.7422@vlsi.waterloo.edu>, ward@vlsi.waterloo.edu (Paul Ward) writes:
> Could someone please explain, briefly and with examples, exactly what
> catch and throw are and when and where they might be used, and what
> relationship they have to logic.

Which catch and throw do you mean?  Do you mean the ``non-local return to
a label with dynamic scope'' things in Lisp-like languages, or the
``Ada-like exception handling things with misleading names'' proposed for
ISO Prolog?

The basic point is that in real-world programming you come up with
situations where it is not possible to succeed with any binding, but
it would be wrong to fail.  Consider, for example,
	get0(C)
issued after the last character of the file has been consumed.
You can't suceed, because there isn't any character to bind C to.
But you can't fail, either, because failure would mean "I _did_
read a character, but it didn't unify with C".  This is an instance
of what I call an ``existence error''; the program has asked for
(some attribute of) a well-identified object which doesn't exist.
(Trying to open a non-existent file for input is another.)

The scheme that I proposed to the BSI at the end of 1984 was
	if_error(Goal, ErrorTerm, Handler)
	signal_error(ErrorTerm)
It is now clear that the argument order for if_error was at the very
least an error of taste.  The ErrorTerm should be in the _same_
argument position in both commands (and in other commands related to
exception handling).  Quintus decided that 'exception' was a better
name than 'error'.  So we have

	if_exception(ErrorTerm, Goal, Handler)

		acts exactly like Goal, unless a call to signal_exception
		occurs while Goal is running, in which case Goal is
		abandoned, variables are reset to the state they had
		before if_exception was started (this includes variables
		in ErrorTerm).  If the error term that was signalled
		unifies with ErrorTerm, the Handler is executed in place
		of the Goal.  (The Handler is _not_ regarded as ``inside''
		the if_exception form; any errors in it will _not_ result
		in the Handler being restarted.)  If the error term that
		was signalled does not unify with ErrorTerm, the error is
		in effect resignalled.

	signal_exception(ErrorTerm)

		makes of copy of ErrorTerm, then keeps on failing until
		it finds an _ancestor_ if_exception(E, Goal, Handler)
		where E unifies with the copy of ErrorTerm.

		I describe this as "failing into the success continuation".

Many built in operations may signal an exception.  For example, floating-
point overflow should signal a representation fault.  There is a mathematically
defined answer, but the system can't represent it, so can't succeed, but it
would be wrong to fail because the answer does exist.

Concerning the relation to logic:

	every solution of if_exception(E,G,H)
	is either a solution of G
	or a solution of (E=T,H) for some term T.

	every solution of var(X), if_exception(X,G,H), var(X)
	is a solution of G.

	every solution of var(X), if_exception(X,G,H), nonvar(X)
	is a solution of (X=T,G) for some term T, where T does
	not share variables with any other term.

	if_exception(E, G, H)
	is identical in effect to
	if_exception(X, G, (X = E -> H ; signal_exception(X))

As a tiny example of exception handling:

	open_input_file(Name0, Name, Stream) :-
		if_exception(existence_error(_,_,_,_),
		    (	open(Name0, read, Stream),
			Name = Name0
		    ),
		    (	format('~&~w does not exist.  Try another name.~%',
				[Name0]),
			read(Name1),
			open_input_file(Name1, Name, Stream)
		    )).

There are many other things that can go wrong with a call to open/3,
but an existence error means that you had a file name that made sense
but failed to name an existing file.


Oh yes, one point.  A pons asinorum of exception handling is to mistake
them for a way of handling interrupts.  Now an interrupt handler might
well decide to signal an exception, but you wouldn't, for example, want
to handle SIGCONT that way...
-- 
Q:  What should I know about quicksort?   A:  That it is *slow*.
Q:  When should I use it?  A:  When you have only 256 words of main storage.
Technical Details
Message-ID: <6388@goanna.cs.rmit.oz.au>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!munnari.oz.au!goanna!ok
References: <3946@n-kulcs.cs.kuleuven.ac.be> <6378@goanna.cs.rmit.oz.au> <1991Jun18.125519.7422@vlsi.waterloo.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!munnari.oz.au!goanna!ok
From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Newsgroups: comp.lang.prolog
Subject: Re: block and exit_block
Message-ID: <6388@goanna.cs.rmit.oz.au>
Date: 19 Jun 91 10:21:39 GMT
References: <3946@n-kulcs.cs.kuleuven.ac.be> <6378@goanna.cs.rmit.oz.au> <1991Jun18.125519.7422@vlsi.waterloo.edu>
Organization: Comp Sci, RMIT, Melbourne, Australia
Lines: 100