[plt-scheme] exception handling

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Tue Jan 20 07:51:24 EST 2009

At Tue, 20 Jan 2009 12:31:12 +0000, Dave Griffiths wrote:
> A quick question about exception handling. I'd like to run a thunk in a
> context where I can capture the error and do something with it in code -
> i.e. keep the program running after the error has occurred. For example
> something like this:
> (define error-happened #f)
> (define (err n)
>   (set! error-happened #t))
> (call-with-exception-handler err (lambda () (modulo 0 1 2)))
> (when error-happened
>   (do-something))
> However, the value of (err) is passed to the uncaught exception handler,
> which in turn stops evaluation. I certainly don't want to turn off the
> normal exception handling globally, so I'm guessing I can use
> (with-handlers) but I'm not sure how.

An exception handler has to escape out of the expression that raised
the exception. And, to escape, you have to create a place to escape to.

The most primitive way to do that is to set a prompt and abort to it:

 (define recover-tag (make-continuation-prompt-tag))

 (define (err n)
   (set! error-happened #t)
   (abort-current-continuation recover-tag 10))

 (define (call-as-recoverable thunk)
    (lambda (v) v)))

 (call-with-exception-handler err (lambda () 
                                    (+ (call-as-recoverable
                                        (lambda () (modulo 0 1 2)))

That's pretty much what `with-handlers' does:

 (define (err n)
   (set! error-happened #t)
   10) ; just return a value, because `with-handlers' handles abort

 (+ (with-handlers ([(lambda (x) #t) err])
      (modulo 0 1 2))

Some Scheme/Lisp systems effectively put a prompt at every call to a
primitive function, so that an exception handler can recover from any
exception that was raised by a primitive by aborting to the call. PLT
Scheme doesn't support that, though.


Posted on the users mailing list.