[plt-scheme] R6RS exception handling and dynamic extent [was: SXML for R6RS]

From: Derick Eddington (derick.eddington at gmail.com)
Date: Thu Jul 10 10:23:09 EDT 2008

On Thu, 2008-07-10 at 06:02 -0600, Matthew Flatt wrote:
> At Thu, 10 Jul 2008 00:36:32 -0700, Derick Eddington wrote:
> > On Wed, 2008-07-09 at 07:18 -0600, Matthew Flatt wrote:
> > > Suppose that you actually want ports to be closed when control escapes
> > > (for any reason), so you write
> > > 
> > >  (define (call-with-input-file* file proc)
> > >    (let ([p #f])
> > >      (dynamic-wind
> > >        (lambda () (set! p (open-input-file file)))
> > >        (lambda () (proc p))
> > >        (lambda () (close-input-port p) (set! p #f)))))
> > > 
> > > and use that, instead. Then, doesn't my objection about `ssax:warn' and
> > > `guard' hold?
> > 
> > Using dynamic-wind like that would have the same issue with any possible
> > exception re-raised by a guard, and if there were multiple guards which
> > re-raise, it would exit and re-enter for each guard.  Or what if
> > somewhere down in proc's dynamic extent it uses a procedure which
> > escapes to some continuation and then re-enters back?  Assuming the
> > dynamic extent will only be entered and exited once just seems like a
> > bad idea unless you can be certain of that.
> You're right.
> Under normal circumstances, you can be sure quite often, because few
> library functions capture and restore continuations. Indeed, in
> building PLT Scheme libraries and tools, we've often found it necessary
> to ensure that a continuation is not restored when unknown code is
> called, which is why PLT Scheme includes constructs like continuation
> barriers.
> > I don't see how making ssax:warn raise an exception
> > singles it out when there are other ways control could escape and
> > re-enter.
> Turning the above around, if a library captures and restores
> continuations, then it's placing an extra burden on users of the
> library to accommodate continuation jumps. That sounds like a big price
> to pay to get warnings from SSAX --- but perhaps I'm not enough of an
> SSAX user to say. If SSAX users understand that functions capture and
> restore continuations anytime that they might report a warning, and if
> they're happy with that API, then it's all fine.

I agree that would be a big price, too big and too unexpected of a
price.  Now I think I realize there's another issue you are considering
that I was not: in PLT at the moment, `raise-continuable' is capturing
its continuation which gets restored if the handler returns, and this is
why my `ssax:warn' would be capturing and restoring continuations.  I
realized I've been assuming this would not be PLT's final design,
because of what the R6RS seems to say about how exception handling and
dynamic extent is supposed to work -- that raising an exception,
continuable or not, calling the handler, and possibly returning for a
continuable exception, does not exit and re-enter the dynamic
extent (unless `guard' handlers which re-raise are involved, but
that's an argument against using `guard' I think, not against using
continuable exceptions).

        (raise obj)    procedure 
        Raises a non-continuable exception by invoking the current
        exception handler on obj. The handler is called with a
        continuation whose dynamic environment is that of the call to
        raise, except that the current exception handler is the one that
        was in place when the handler being called was installed. When
        the handler returns, a non-continuable exception with condition
        type &non-continuable is raised in the same dynamic environment
        as the handler.
        (raise-continuable obj)    procedure 
        Raises a continuable exception by invoking the current exception
        handler on obj. The handler is called with a continuation that
        is equivalent to the continuation of the call to
        raise-continuable, with these two exceptions: (1) the current
        exception handler is the one that was in place when the handler
        being called was installed, and (2) if the handler being called
        returns, then it will again become the current exception
        handler. If the handler returns, the values it returns become
        the values returned by the call to raise-continuable.

Maybe I'm reading into this too much thinking it means the dynamic
extent will not be exited and re-entered.  But if my interpretation is
wrong, doesn't that mean any and all uses of `raise-continuable' are
going to be effectively verboten in an implementation that captures and
restores continuations, because they'll be imposing that unexpectedly?
(I agree imposing that unexpectedly would be bad.)  But then what's the
use of continuable exceptions, &warning, and an initial/default handler
that returns for non-&serious?

In Ikarus, calling `raise' or `raise-continuable', calling the handler,
the handler's dynamic extent possibly calling `raise' or
`raise-continuable', and the handler returning all do not capture or
restore continuations, it's all one series/stack of normal procedure
calls and returns (again, unless `guard' handlers are called).

: Derick

Posted on the users mailing list.