[R6RS] smaller condition hierarchy

Matthew Flatt mflatt at cs.utah.edu
Thu May 11 00:08:47 EDT 2006

As I noted before, MzScheme's exception hierarchy has steadily shrunk
over the years. We've found that most of the differentiation among
exceptions wasn't used.

FWIW, here's the current exception hierarchy in MzScheme:

 exn : the root
   break : asynchronous break signal 
   fail : exceptions that represent errors 
     contract : inappropriate run-time use of a function or syntactic form 
       arity : application with the wrong number of arguments 
       divide-by-zero : divide by zero 
       continuation : attempt to cross a continuation barrier 
       variable : unbound/not-yet-defined global or module variable 
     syntax : syntax error, but not a read error 
     read : read parsing error 
       eof : unexpected end-of-file 
       non-char : unexpected non-character 
     filesystem : error manipulating a filesystem object 
       exists : attempt to create a file that exists already 
       version : version mismatch loading an extension 
     network : TCP and UDP errors 
     out-of-memory : out of memory (sometimes)
     unsupported : unsupported feature 
     user : for end users (i.e., not a program defect)

Currently, most exception handlers in PLT Scheme code either 

 * catch exn:fail, with the implication that exn:break is propagated
   (which is desirable because exn:break usually means that the user
   hit Ctl-C)

 * catch everything, clean up, then re-raise the caught exception
   (including exn:break)

Some handler catch exn:fail:filesystem or exn:fail:network, because the
filesystem or network is expected to fail and the failure can be handled.

exn:fail:read:eof is unusually specific in the above hierarchy, but for
REPLs that must determine when an input expression is complete.

exn:fail:filsystem:exists is also unusually specific; it is used to
detect when file creation fails because the target file already exists.

exn:fail:user is for errors to be seen by end-users; if the exception
isn't caught, the default error printer suppresses the a stack trace
for exn:fail:user.

exn:fail:contract:arity is mainly useful for testing.

exn:fail:syntax exceptions appear when an `eval'- or `load'-like
function encounters an ill-formed expression.

exn:fail:read:non-char and exn:filesystem:verion are weird, and you
should ignore them. exn:fail:contract:continuation is also highly
MzScheme-specific, and I doubt that it's useful even in MzScheme.
Finally, exn:fail:contract:divide-by-zero is surely useless, except
maybe for tutorials.

Single-inheritance in the hierarchy above is occasionally limiting. For
details like source location, which is relevant in different parts of
the hierarchy, we use properties instead of sub-types.


Experience with MzScheme may not carry over to the R6RS setting, but if
it does, the condition hierarchy might be simplified to something like
the following:

      &non-continuable   ; handler wasn't expected to return

Changes from the original:

 Added a &user condition

 Dropped &no-infinities and &no-nans.

 Added &filesystem and &network under &io; consider also adding
  &exists for specially signaling that a file cannot be created
  because it already exists

 Moved &undefined to a sub-condition of &defect, and dropped
  &syntax. (If we need &syntax after all, I don't think &undefined
  should be a sub-condition.)

 Merged &domain, &incompatible, and &result into &contract,
  dropping all sub-conditions


More information about the R6RS mailing list