unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: Chris Vine <vine35792468@gmail.com>
To: Andy Wingo <wingo@pobox.com>
Cc: guile-users@gnu.org, guile-devel@gnu.org
Subject: Re: GNU Guile 2.9.5 Released [beta]
Date: Sun, 1 Dec 2019 20:41:42 +0000	[thread overview]
Message-ID: <20191201204142.0388791e61fa443e615605da@gmail.com> (raw)
In-Reply-To: <87lfs8kkao.fsf@pobox.com>

On Fri, 22 Nov 2019 16:22:39 +0100
Andy Wingo <wingo@pobox.com> 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



  parent reply	other threads:[~2019-12-01 20:41 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-22 15:22 GNU Guile 2.9.5 Released [beta] Andy Wingo
2019-11-22 16:01 ` tomas
2019-12-01 20:41 ` Chris Vine [this message]
2020-01-05 20:15   ` Andy Wingo
2020-01-05 23:26     ` Chris Vine
2020-01-06 20:34       ` Andy Wingo
2020-01-06 23:14         ` Chris Vine
2020-01-07 21:53           ` Andy Wingo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191201204142.0388791e61fa443e615605da@gmail.com \
    --to=vine35792468@gmail.com \
    --cc=guile-devel@gnu.org \
    --cc=guile-users@gnu.org \
    --cc=wingo@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).