Next: , Up: Programmatic Error Handling   [Contents][Index]


6.27.3.1 Catching Exceptions

A common requirement is to be able to show as much useful context as possible when a Scheme program hits an error. The most immediate information about an error is the kind of error that it is – such as “division by zero” – and any parameters that the code which signalled the error chose explicitly to provide. This information originates with the error or throw call (or their C code equivalents, if the error is detected by C code) that signals the error, and is passed automatically to the handler procedure of the innermost applicable catch or with-throw-handler expression.

Therefore, to catch errors that occur within a chunk of Scheme code, and to intercept basic information about those errors, you need to execute that code inside the dynamic context of a catch or with-throw-handler expression, or the equivalent in C. In Scheme, this means you need something like this:

(catch #t
       (lambda ()
         ;; Execute the code in which
         ;; you want to catch errors here.
         ...)
       (lambda (key . parameters)
         ;; Put the code which you want
         ;; to handle an error here.
         ...))

The catch here can also be with-throw-handler; see Throw Handlers for information on the when you might want to use with-throw-handler instead of catch.

For example, to print out a message and return #f when an error occurs, you might use:

(define (catch-all thunk)
  (catch #t
    thunk
    (lambda (key . parameters)
      (format (current-error-port)
              "Uncaught throw to '~a: ~a\n" key parameters)
      #f)))

(catch-all
 (lambda () (error "Not a vegetable: tomato")))
-| Uncaught throw to 'misc-error: (#f ~A (Not a vegetable: tomato) #f)
⇒ #f

The #t means that the catch is applicable to all kinds of error. If you want to restrict your catch to just one kind of error, you can put the symbol for that kind of error instead of #t. The equivalent to this in C would be something like this:

SCM my_body_proc (void *body_data)
{
  /* Execute the code in which
     you want to catch errors here. */
  ...
}

SCM my_handler_proc (void *handler_data,
                     SCM key,
                     SCM parameters)
{
  /* Put the code which you want
     to handle an error here. */
  ...
}

{
  ...
  scm_c_catch (SCM_BOOL_T,
               my_body_proc, body_data,
               my_handler_proc, handler_data,
               NULL, NULL);
  ...
}

Again, as with the Scheme version, scm_c_catch could be replaced by scm_c_with_throw_handler, and SCM_BOOL_T could instead be the symbol for a particular kind of error.


Next: , Up: Programmatic Error Handling   [Contents][Index]