Title

SRFI 23: Error reporting mechanism

Author

Stephan Houben

Status

This SRFI is currently in ``final'' status. To see an explanation of each status that a SRFI can hold, see here. You can access the discussion via the archive of the mailing list.

Abstract

A mechanism is proposed to allow Scheme code to report errors and abort execution. The proposed mechanism is already implemented in several Scheme systems and can be implemented, albeit imperfectly, in any R5RS conforming Scheme.

Rationale

R5RS Scheme requires certain operations to signal an error when they fail. "Signalling an error" means that implementations must detect and report the error. Moreover, R5RS encourages, but not requires, implementations to signal an error in many more circumstances.

However, there is no direct way for the Scheme application programmer to report an error that occured in his or her own application. This means that Scheme procedures created by applications or libraries are in this respect not on equal footing with procedures provided by the Scheme system.

Many Scheme systems already provide a mechanism that allows application code to report an error. At least the following implementations support such a mechanism: Bigloo, Guile, MIT Scheme, PLT Scheme, RScheme, Scsh, SCM, all implementations supported by SLIB. Of these implementations, the following have an error mechanism compatible with this SRFI: Guile, MIT Scheme, PLT Scheme, RScheme, Scsh. The implementation in SLIB has a different name than the one proposed in this SRFI.

To summarise, many implementations already have the error reporting mechanism described in this SRFI and others are easily made compatible with this SRFI. This shows that the proposed mechanism is considered useful and that it is easy to implement in most major implementations.

Specification

The following procedure should be provided:

(error <reason> [<arg1> [<arg2> ...]])

The argument <reason> should be a string. The procedure error will signal an error, as described in R5RS, and it will report the message <reason> and the objects <arg1>, <arg2>, .... What exactly constitutes "signalling" and "reporting" is not prescribed, because of the large variation in Scheme systems. So it is left to the implementor to do something reasonable. To that end, a few examples of possible behaviour are given.

  1. Display <reason> and <arg1>... on the screen and terminate the Scheme program. (This might be suitable for a Scheme system implemented as a batch compiler.)
  2. Display <reason> and <arg1>... on the screen and go back to the read-evaluate-print loop. (This might be suitable for an interactive implementation).
  3. In the case of a multi-threaded system: terminate the current thread, but do not terminate the other threads. Possibly make the arguments to error available to other threads in some way. See the thread-join! mechanism in SRFI-18 on how this could be done.
  4. Package <reason> and <arg1>... up into an error object and pass this error object to an exception handler. The default exception handler then might do something as described in points 1 to 3.
  5. In the case of a Scheme system that runs completely unattended and that has no way to notify a human, the only reasonable course of action might be to do nothing at all. However, this should be considered a last resort. Clearly, if all implementors would choose this strategy, this SRFI would not be very useful.
An implementation might report more information than just <reason> and <arg1>... . For instance, it might report the procedure name in which the error occured or even print a stack trace. However, this will require additional support in the Scheme implementation.

Why error is a procedure

It is conceivable to allow error to be a special form, such as a macro, rather than a procedure. This might make providing information such as the source code location easier. This possibility has been considered, but rejected, for two reasons.
  1. Since error accepts a variable number of arguments, it could occasionally be useful to use apply to call error. However, this is not possible if error was allowed to be a special form.
  2. Since error is currently a procedure in all Scheme implementations mentioned above, it doesn't seem all that worthwhile to allow it to be a special form.

Implementation

An implementation that works in almost any R5RS Scheme is the following:
  (define (error reason . args)
      (display "Error: ")
      (display reason)
      (for-each (lambda (arg) 
                  (display " ")
		  (write arg))
		args)
      (newline)
      (scheme-report-environment -1))  ;; we hope that this will signal an error
This implementation has a flaw, namely, in many implementations this will actually print 2 messages.
  1. The message message, followed by objs, and
  2. A message about scheme-report-environment getting an invalid argument.
This might be confusing to the user.

The SLIB procedure slib:error works like the error procedure described in this document. Thus, when SLIB is loaded, error can be defined as:

  (define error slib:error)

If SRFI 18 is supported, it is allowed (but not required) to implement error in terms of the exception mechanism of SRFI 18.

  (define (error reason . args)
    (raise (make-error-exception reason args)))
Here, make-error-exception is implementation dependent.

Copyright

Copyright (C) Stephan Houben (2001). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Scheme Request For Implementation process or editors, except as needed for the purpose of developing SRFIs in which case the procedures for copyrights defined in the SRFI process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the authors or their successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Editor: Mike Sperber
Last modified: Fri Sep 19 19:33:33 CDT 2003