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

Error objects in general

This page is part of the web mail archives of SRFI 77 from before July 7th, 2015. The new archives for SRFI 77 contain all messages, not just those from before July 7th, 2015.

I've been thinking about the behavior of error objects. And
here are my thoughts....

I think that when a "live" error object is stored or written, it
should be possible to read it back and get a value that says
an error object was stored or written.  But what you read back
should be a "stale" error object, so you can tell the difference
between a "live" error and a "stored and recovered" error.  This
sorta implies that there are two cases of most error objects,
"Live" and "stale", the same way there are two cases of letters
in the Roman alphabet.  When you write a "stale" error and read
it back, it should be the same "stale" error.

So, for example:

(define plag (/ #e1 #e0)) ;; the result of the error expression itself.

(set! bar plag)  ;; the result of referring to it.
(define gref (cons plag 'foo))  ;; ditto.

(error-object? plag) ==> #t
(error-object? bar) ==> #t
(error-object? (car gref)) ==> #t
(live-error? plag) ==> #t
(live-error? bar) ==> #f
(live-error? (car gref)) ==> #f

This would preserve read/write invariance for (stale) errors,
and provides a framework that allows the preservation of error
information through write/read cycles even for live errors
(although they will become stale during the write/read cycle)
while enabling people to tell the difference between an error
originating in the reader and an error read by the reader.

The behavior I'd most like for error objects in a language
would be that any routine recieving an error object as an
argument, unless it has an error-handler specified, immediately
returns that error object without actually running any of its
own code.

NaNs work mostly this way, except that the abort happens only at
the level of fundamental operations like + and - rather than
through the entire language.  If we think that this aspect of
NaNs is a good idea, we should consider the possibility of including
it in ordinary function call semantics for user-defined functions as
well.  If we don't think that it's a good idea, we should mask
it in the math operations.  And finally, if we think it's a good
idea for the few fundamental math operations where IEEE defines
it and not otherwise, we need to decide why.

And, for what it's worth, this is a simple, clean, general error-
handling and error-signalling mechanism that's straightforward to
implement and simple to specify and prove things about, and I think
it's possibly a better model than most I've seen advanced.

There are several viable implementation strategies, including
compilation to routines that use throw/catch, or stepwise handling
where each procedure call would now have to iterate through the
arguments to find any error objects, and, on finding one, check
for a handler.  And it would require some way of managing the
association of error handlers with particular routines.