[plt-scheme] call-with-exception-handler inside with-handlers

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Fri Dec 21 19:51:42 EST 2007

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

 (define (call-with-NESTED-exception-handler handler body)
    (call-with-exception-handler handler body)

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))))
      (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.


Posted on the users mailing list.