chickadee » simple-exceptions

Exceptions made easy

Chicken's condition system is versatile and flexible, but apart from the two high level exception handlers, handle-exceptions and condition-case, not very user friendly. In particular the low-level exception handler, with-exception-handler, must be used with extreme care to avoid non-terminating loops. Moreover creating and inspecting condition-objects is cumbersome.

So this library introduces some procedures and macros to facilitate matters. Exceptions are introduced as special conditions, to be more precise, [composite] conditions of kind exn, which all have properties message, location and arguments, which can easily be accessed by procedures of that very name. They are constructed by separating the general property, message, and the general kinds, from the special properties, location and arguments, the latter being considered as parameters of an exception.

In other words, one can define a global exception-variable of a special kind, e.g.

(define assert-exn (make-exception "assertion violated" 'assert))

which can then be used within the definition of a procedure, foo say, as follows

(raise (assert-exn 'foo 'xpr))

Here, raise is a version of abort with improved error messages.

The exception raised can now be handled in the usual way, preferably

(condition-case (foo arg) ((exn assert) ...))

or

(handle-exceptions exn (if ((exception-of? 'assert) exn) ...) (foo arg))

but other handlers are provided as well, in particular, guard of R6RS and R7RS, and with-exn-handler, which has the same syntax as Chicken's with-exception-handler, but avoids its subtleties. For example, the follwing code does what you expect, it returns 0.

(with-exn-handler (lambda (exn) 0) (lambda () (car '())))

without looping forewer, what with-exception-handler would have done.

The interface

current-exception-handler

current-exception-handler #!optional new-handlerparameter

chicken's handler parameter reexported.

exceptions

exceptions #!optional symprocedure

documentation procedure.

exception?

exception? xprprocedure

type predicate. Note, that each exception is a condition of kind exn.

exn?

exn? xprprocedure

alias to exception?

exception-of?

exception-of? kind-keyprocedure

returns a unary predicate, which checks, if its argument expression is an exception of kind kind-key, a symbol.

exn-of?

exn-of? kind-keyprocedure

alias to exception-of?

make-exception

make-exception msg #!rest kind-keysprocedure

Returns a procedure of at least one argument, a symbol describing the location of its call, and an optional other argument, a list of arguments, which creates an exception of kinds kind-keys, message msg, as well as the given location and arguments.

make-exn

make-exn msg #!rest kind-keysprocedure

alias to make-exception

location

location exnprocedure

returns the location property of its exception argument.

message

message exnprocedure

returns the message property of its exception argument.

arguments

arguments exnprocedure

returns the arguments property of its exception argument.

raise

raise exnprocedure

raises its argument, i.e. calls (current-exception-handler) with exn. In essence chicken's abort.

with-exn-handler

with-exn-handler handler thunkprocedure

A save version of chicken's low-level with-exception-handler. Sets the current-exception-handler to handler for the dynamic extent of its call and executes thunk in this context.

condition-case

(condition-case xpr ([var] (kind ...) body) . other-clauses)))syntax

Chicken's highest level exception-handler reexported.

handle-exceptions

(handle-exceptions exn handle-xpr xpr . xprs)syntax

Chicken's high level exception handler reexported.

guard

(guard (exn cond-clause . cond-clauses) xpr . xprs)syntax

The high level exception handler of R6RS and R7RS. Sets the current-exception-handler to an exception-handler created from exn und the supplied cond-clauses for the dynamic extent of its call and executes the body xpr . xprs in this context.

argument-exception

argument-exception loc arg ...procedure

raised when a precondition is violated. Can be catched with (exn argument)

argument-exn

argument-exn loc arg ...procedure

alias to argument-exception

result-exception

result-exception loc arg ...procedure

raised when a postcondition is violated. Can be catched with (exn result)

result-exn

result-exn loc arg ...procedure

alias to result-exception

Outsourced

The following routines are outsourced to the checks egg with slightly modified syntax: assert*, <<, <<<, >>, >>>, named-lambda, true?, false?

Examples

(import simple-exceptions)

(define foo-exn (make-exception "foo-msg"))
(define bar-exn (make-exception "bar-msg" 'bar))
(exception? (foo-exn 'nowhere))

(bar-exn 'nowhere)
(exception? (bar-exn 'nowhere)) ; -> #t

((exception-of? 'bar) (bar-exn 'nowhere)) ; -> #t
((exception-of? 'bar) (foo-exn 'nowhere)) ; -> #f

(arguments ((make-exception "msg" 'baz) 'nowhere "bar"))
  ; ,> (list "bar")

((exception-of? 'key)
 ((make-exception "msg" 'key) 'nowhere))
  ; -> #t

(define list-empty-exn
  (make-exception "argument list empty" 'list-empty))

(define (try-car lst)
  (if (null? lst)
    (raise (list-empty-exn 'try-car lst))
    (car lst)))

;; exception handler procedure
(with-exn-handler
  (lambda (exn)
    (if ((exception-of? 'list-empty) exn)
      #f
      #t))
  (lambda () (try-car '())))
  ; -> #f

(with-exn-handler (lambda (e) 0) (lambda () (/ 5 0))) ; -> 0

(guard
  (exn (((exception-of? 'foo) exn)
        (location exn))
       ((exception? exn)
        (message exn))
       (else
         (arguments exn)))
  (raise ((make-exception "msg" 'foo)
           'location-unknown)))
  ; -> 'location-unknown)

Last update

Feb 02, 2019

Author

Juergen Lorenz

Repository

This egg is hosted on the CHICKEN Subversion repository:

https://anonymous@code.call-cc.org/svn/chicken-eggs/release/5/simple-exceptions

If you want to check out the source code repository of this egg and you are not familiar with Subversion, see this page.

License

Copyright (c) 2014-2019, Juergen Lorenz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission. 
  
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Version History

1.3
<<< and friends outsourced to checks
1.2
<<< and >>> with additional optional argument
1.1
zero argument case added to << and (<<< loc)
1.0
port of chicken-4's version 0.6

Contents »