[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: more srfi-12 rationale?



Thanks to Richard for pointing out the discussion on the RnRS authors
list.  I have added a reference to it to the SRFI FAQ page.

I read through the 50-odd messages about this topic from 1995/96 and
thought about this a bit more.

>>>>> On Fri, 15 Oct 1999 22:54:39 -0400, Dave Mason <dmason@xxxxxxxxxxxxxxx> said:
> Is the definition of ABORT supposed to be recursive?  The semantics
> of that are very unclear.  Shouldn't it be unrolling exception
> handlers?

After thinking about it, I realized that HANDLE-EXCEPTIONS does the
unwind of the exception handler.  It probably wouldn't be a bad idea
for WITH-EXCEPTION-HANDLER to recommend that people should normally
use HANDLE-EXCEPTIONS.

But there's still a problem with the implementation.  Try:
	(handle-exceptions
	 foo
	 (abort 'barf)
	 (abort 'blat))
but have your hand near your ^C key.

It's pretty clear to me that the exception handler should have the
exception context of the HANDLE-EXCEPTIONS, rather than itself!

In reading the RnRS archive, I became quite convinced (primarily based
on the compelling arguments of one of the authors of SRFI-12) that
setting up an exception handler and taking an exception should be
*very* cheap.  The SRFI-12 exception mechanism *is* cheap, but the
*condition* mechanism isn't cheap at all.  It requires (in general)
creating an object for every raised exception.

The point of conditions, as I understand them, is that there is some
fixed information associated with raising an exception (such
EOF-IN-DATUM) and some variable data (such as the port).  An exception
handler might want to ascertain all sorts of information about the
exception (particularly in the common-lisp interactive debugging
model).  I suggest that this should be separated and the definition
look more like:

  (HANDLE-EXCEPTION
     (lambda (exn-static exn-dynamic fn)
         ...)
     e1 e2 ...)

Where ``exn-static'' is the fixed data specific to the exception
raised (could be specified to be a symbol, a list, a ``condition''
value, or anything else you like), ``exn-dynamic'' is the dynamic
data, and ``fn'' is a function used to extract information from the
static and dynamic data.  ``fn'' takes at least 3 parameters:
exn-static, exn-dynamic, and a selector to choose the information to
retrieve:
	(fn exn-static exn-dynamic 'condition-predicate kind-key)
	(fn exn-static exn-dynamic 'message-english)

This doesn't seem terribly unreasonable, and it means that in almost
all cases the exn-static and fn parameters to the handler will be
constants and the exn-dynamic will be a value already available (part
of the operation).  So no cons'ing or other object creation is
necessary.  The fn parameter might reasonably be left out of the
specification, but it has the potential of making exceptions more
efficient.

I don't like the fact that it needs to do a dynamic-wind and a call/cc
to set up an exception and the continuation is actually called whether
or not an exception is raised (because it appears that dynamic-wind
isn't values-aware).  This seems a lot heavier-weight than I would
like.  It appears that this is because exception handlers can return
as well as abort (exceptions in ML are only of the latter type).
Personally, I'd be perfectly happy with exceptions that only could
abort.

../Dave