[plt-scheme] exception handling
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)
(call-with-continuation-prompt
thunk
recover-tag
(lambda (v) v)))
(call-with-exception-handler err (lambda ()
(+ (call-as-recoverable
(lambda () (modulo 0 1 2)))
5)))
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))
5)
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.
Matthew