[plt-scheme] call-with-exception-handler inside with-handlers
At Fri, 21 Dec 2007 21:29:15 +0100, "Marco Maggi" wrote:
> why the form:
>
> (with-handlers (((lambda (o)
> #t) (lambda (exn)
> (list 'out exn))))
> (call-with-exception-handler
> (lambda (exn)
> (list 'error exn))
> (lambda ()
> (raise 123))))
>
> gives me an uncaught exception "(error 123)" rather than
> simply returning the value "(out 123)"? If the explanation
> involves continuations, continuation marks or prompts: just
> tell me to forget it (I don't wanna know :-).
Both `with-handlers' and `call-with-exception-handler' evaluate the
body expression/thunk in tail position with respect to setting the
exception. So, the `call-with-exception-handler' is overwriting the
handler installed by `with-handlers'.
(Ok, yes, it's really about continuations and continuation marks.)
Here's a variant of `call-with-exception-handler' that does what you
want:
(define (call-with-NESTED-exception-handler handler body)
(begin0
(call-with-exception-handler handler body)
(void)))
That is, it installs an exception handler in a non-tail position, so it
doesn't overwrite the existing one:
(with-handlers (((lambda (o)
#t) (lambda (exn)
(list 'out exn))))
(call-with-NESTED-exception-handler
(lambda (exn)
(list 'error exn))
(lambda ()
(raise 123))))
`call-with-exception-handler' has the lower-level behavior in case that
someone needs it, but `call-with-NESTED-exception-handler' is probably
the more expected behavior. Maybe v4 should use the latter as
`call-with-exception-handler' and provide the more primitive behavior
as `call-with-exception-handler*'.
Also, though it goes without saying that the reference docs need work,
they seem incomplete even to me in this case. I'll work on that, in
addition to planning a less dense explanation for the guide.
Matthew