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

Re: exception systems



This is a response to Aubrey Jaffer's comments on the
six purposes that I suggested for an exception system.
All quotations are from Jaffer's message, which quotes
my numbered purposes.

>    1.  So an application can use exceptions as a control structure
>    without having to load an SLIB module or use
>    CALL-WITH-CURRENT-CONTINUATION.
> 
> Avoiding the loading of files...is a major new restriction on
> implementations.....What large benefit justifies restricting
> implementations thus?

I was not suggesting any such restriction.  I was noting
that one possible purpose of standardizing on an exception
system for R5RS is to avoid the inconvenience of having to
load a module in order to use exceptions.

My personal opinion is that purpose #1 is EXTREMELY LAME.

>    2.  So an application can give up when it detects an untenable
>    situation.
> 
> This is the situation currently.  An application program has no
> recourse when an error is signaled.

That is NOT the current situation, as there is no way to
signal an error in R4RS Scheme.  In order to give up when
an untenable situation is detected, a program must use
CALL-WITH-CURRENT-CONTINUATION to capture an appropriate
exit point.  The original exception proposal of last fall
was essentially a bit of syntactic sugar for making these
calls to CALL-WITH-CURRENT-CONTINUATION.

My personal opinion is that purpose #2 is LAME.

>    4.  So an application can give meaning to some situation that
>    the language standards describe as an error.  For example, an
>    application might want (CAR '()) to evaluate to #f, or (+ LOG EXP)
>    to be (LAMBDA (X) (+ (LOG X) (EXP X))).
> 
> Scheme programs can already can accomplish these tasks by redefining
> CAR and +.  By defining them, a program declares to a compiler that
> these procedures can behave differently from the built-in procedures.

This works fine provided it is acceptably efficient.  An
adequate exception system provides a potentially more efficient
way to do this.

Some compilers for Scheme can be made to generate efficient
inline code for CAR and +.  For some programs, the efficiency
gained by inlining is essential.  Without it, the program would
have to be written in some language other than Scheme.

Redefining CAR and + for these programs may sacrifice too much
performance.  It is often the case that CAR and + don't need to
be completely redefined, but merely extended.  If so, then the
performance benefits of inline code can be retained for the
common (inlined) cases, while the uncommon (extended) cases
are handled through an exception system.

> To redefine built-in procedures by creating exception handlers would
> seem to make compiling extremely difficult....

It doesn't, because in most implementations these built-in
procedures are already written to signal an exception (using
some implementation-dependent exception system) when they are
passed an argument that is outside their domain of definition.

My personal opinion is that purpose #4 is irrelevant for most
programs but is very important for a few.

>    5.  So an implementation can inline a common case, but take an
>    exception to handle less common cases.  For example, (+ X 1)
>    might generate a MIXED-MODE-ARITHMETIC exception if the value
>    of X is not a small exact integer.  This usage would always be
>    implementation-dependent.
> 
> The objections to 4 apply here too.  Exceptions seem a very roundabout
> way to extend arithmetic operations to new types.  Don't `object' or
> `type' systems specify such extensions more cleanly?

Yes, but dynamic method lookup is often implemented by inlining
a common (or cached) case and signalling an exception to handle
all other cases.  This common implementation technique therefore
presupposes an adequate exception system.

My personal opinion is that purpose #5 is essential for
efficient implementation of Scheme's generic arithmetic.

> I think goals 2, 3 and 6 are well-founded and desirable.  It would
> help me to understand handlers to see some examples of exception
> handlers from real programs.

To illustrate purposes #4 and #5, consider the following SPARC
code for (- x 1), compiled with inlining permitted for the -
procedure:

        tsubicc  4 $r.reg1 $r.reg1
        bvc      L1
        addi     4 $r.reg1 $r.reg1      ; MINUS:NON-FIXNUM exception
        ori      4 $r.g0 $r.argreg2
        jmpli    1104 $r.globals $r.o7
        orr      $r.g0 $r.reg1 $r.result
        orr      $r.g0 $r.result $r.reg1
    L1:

If x is a small exact integer, then it takes two SPARC
instructions to evaluate (- x 1).

If x is not a small exact integer, then this code signals
a MINUS:NON-FIXNUM exception.  The handler for that exception
handles the case where both arguments to - are inexact reals.
Otherwise it signals a MINUS:UNCOMMON exception.  The handler
for that exception handles all other cases for which the -
procedure is defined in R4RS.  Otherwise it signals a
MINUS:NON-NUMBER exception.

The handler for the MINUS:NON-NUMBER exception can extend
the domain of the - procedure however it wants.

If x is 3.14159, then the evaluation of (- x 1) involves
signalling, handling, and returning from two exceptions.
This is feasible only if the exception system is safe and
efficient.

> As for goal 6, a global timer resource is of limited usefullness
> because a program using the timer must know that no other code uses
> it....

I have used timer exceptions in MacScheme for the following
purposes:

  *  To convert a graphical user interface based on polling
     into an interrupt-driven model.
  *  To implement lightweight concurrent tasks.  Concurrent
     tasks allow editing to proceed while a computation is
     in progress.  They are also useful for many other user
     interface tasks such as blinking the insertion point in
     a text editor, or updating a graph to show the progress
     of some computation.
  *  To profile a program in order to improve its performance.

Clearly many examples of purpose #4 and all examples of purposes
#5 and #6 will be implementation-dependent.  On the other hand,
it would be desirable for the R5RS exception system to support
these purposes.  Otherwise most implementations will have to
support two distinct exception systems: the R5RS "exception"
system and the "native" exception system.  Interfacing these
two distinct systems would be problematic, and having two
distinct systems would be confusing to programmers if the more
generally useful "native" exception system were made available.

Will