guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GNU Guile 2.9.5 Released [beta]


From: Chris Vine
Subject: Re: GNU Guile 2.9.5 Released [beta]
Date: Sun, 1 Dec 2019 20:59:02 +0000

Sorry, a resend to guile-user - the copy to that mailing list was
misaddressed.

------------------------------
On Fri, 22 Nov 2019 16:22:39 +0100
Andy Wingo <address@hidden> wrote:
> We are pleased to announce GNU Guile release 2.9.5.  This is the fifth
> pre-release of what will eventually become the 3.0 release series.
[snip]
> ** Reimplementation of exceptions
> 
> Since Guile's origins 25 years ago, `throw' and `catch' have been the
> primary exception-handling primitives.  However these primitives have
> two problems.  One is that it's hard to handle exceptions in a
> structured way using `catch'.  Few people remember what the
> corresponding `key' and `args' are that an exception handler would see
> in response to a call to `error', for example.  In practice, this
> results in more generic catch-all exception handling than one might
> like.
> 
> The other problem is that `throw', `catch', and especially
> `with-throw-handler' are quite unlike what the rest of the Scheme world
> uses.  R6RS and R7RS, for example, have mostly converged on
> SRFI-34-style `with-exception-handler' and `raise' primitives, and
> encourage the use of SRFI-35-style structured exception objects to
> describe the error.  Guile's R6RS layer incorporates an adapter between
> `throw'/`catch' and structured exception handling, but it didn't apply
> to SRFI-34/SRFI-35, and we would have to duplicate it for R7RS.
> 
> In light of these considerations, Guile has now changed to make
> `with-exception-handler' and `raise-exception' its primitives for
> exception handling and defined a hierarchy of R6RS-style exception types
> in its core.  SRFI-34/35, R6RS, and the exception-handling components of
> SRFI-18 (threads) have been re-implemented in terms of this core
> functionality.  There is also a a compatibility layer that makes it so
> that exceptions originating in `throw' can be handled by
> `with-exception-hander', and vice-versa for `raise-exception' and
> `catch'.
> 
> Generally speaking, users will see no difference.  The one significant
> difference is that users of SRFI-34 will see more exceptions flowing
> through their `with-exception-handler'/`guard' forms, because whereas
> before they would only see exceptions thrown by SRFI-34, now they will
> see exceptions thrown by R6RS, R7RS, or indeed `throw'.
> 
> Guile's situation is transitional.  Most exceptions are still signalled
> via `throw'.  These will probably migrate over time to
> `raise-exception', while preserving compatibility of course.
> 
> See "Exceptions" in the manual, for full details on the new API.

Is this rewrite, and the new with-exception-handler procedure, an
opportunity to think about standardization of guile's implementation of
the R6RS/R7RS 'guard' form, or at least think about what is wanted for
'guard'?

The formal semantics (including specimen implementation) of 'guard' for
R6RS with the corrigendum to §7.1 of the standard library at
http://www.r6rs.org/r6rs-errata.html, and for R7RS without corrigendum
(at §4.2.7 and §7.3, page 72 of the standard), is:

(i) to evaluate the guard body within a block with its own continuation
(as constructed by call/cc);

(ii) if an exception is thrown, evaluate the handler (and its cond
clauses) in the dynamic context of the original caller of 'guard' via
that continuation;

(iii) if no matching cond clause and no else clause is found, return to
the dynamic environment of the original 'raise' and re-raise the
exception with 'raise-continuable', even for non-continuable
exceptions.

If a fully conforming R6RS/R7RS implementation runs this code:

  (guard (exn [(equal? exn 5) #f])
    (guard (exn [(equal? exn 6) 'never-reached])
      (dynamic-wind
        (lambda () (display "in") (newline))
        (lambda () (raise 5))
        (lambda () (display "out") (newline)))))

the code evaluates to #f and should print this:

  in
  out
  in
  out

In chez scheme it does so.  In most other implementations (including
guile and racket) it seems to print:

  in
  out

Guile 2.9.5 appears to implement 'guard' this way:

(i) to evaluate the guard body within a block with its own continuation
(as constructed by call/ec);

(ii) if an exception is thrown, evaluate the handler (and its cond
clauses) in the dynamic environment of the guard body within which the
raise occurred (apart from the current exception handler which is
reset);

(iii) if no matching cond clause and no else clause is found, re-raise
the exception with 'raise' within the dynamic context of that guard
body.

I don't especially like the mandated behaviour of 'guard', which seems
to be intended to allow the guard form to handle continuable
exceptions as continuable elsewhere in the call stack, which seems
fairly pointless to me.  If this is to be departed from, then how about
doing what most people expect of a high-level exception form, and to
unwind the stack by executing the cond clauses within the dynamic
context of the caller of 'guard' (as R6RS/R7RS do), not in that of the
guard body, and then if a re-throw is necessary do it with 'raise'
within that context instead of returning to the guard body to do so?
I think this could be achieved simply by executing
with-exception-handler in the guard0 syntactic form with #unwind set to
true.

Chris



reply via email to

[Prev in Thread] Current Thread [Next in Thread]