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

On Sun 01 Dec 2019 21:41, Chris Vine <vine35792468@gmail.com> writes:

> 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

I really think the standards messed up regarding the specification of
"guard":

  http://scheme-reports.org/mail/scheme-reports/msg03247.html

But those ships have sailed and are now lost at sea.  Guile currently
has two separate implementations of "guard" for SRFI-34 (used by R7RS)
and R6RS.  It would seem that besides not respecting the specification,
the R6RS one is broken, as it expects the "cond" clauses to evaluate to
a single value.

For SRFI-34 (and R7RS), after the exception refactor, I did a re-write
to give a shot at implementing the specified behavior.  It works with a
caveat:  because it uses delimited continuations as the rewind
mechanism, and Guile has a limitation that some delimited continuations
can't be rewound (if the continuation bounces through C), then
re-raising the exception fails because the context can't be rewound.
This can cause previously working programs to break!

Which makes me think, if call/cc (rather than call-with-prompt /
abort-to-prompt) is necessary to implement "guard", we are in a bad
place and we should specify something else.

I have long thought that the right thing to do is this: we evaluate the
"cond" tests in the dynamic environment of the "raise".  Then if a test
succeeds, we unwind and run the corresponding consequent.  That way
there's no rewinding.  Here's an implementation:

  (define-syntax guard
    (syntax-rules (else)
      ((guard (var (t e e* ...) ...) body body* ...)
       (let ((tag (make-prompt-tag)))
         (call-with-prompt
          tag
          (lambda ()
            (with-exception-handler
             (lambda (var)
               (cond
                (t (abort-to-prompt tag (lambda () e e* ...)))
                ...)
               (raise var))
             (lambda ()
               body body* ...)))
          (lambda (k thunk)
            (thunk)))))))

Though I think it might be reasonable to use "raise-continuable" instead
of "raise" if nothing matches.

WDYT?

Andy



  reply	other threads:[~2020-01-05 20:15 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
2020-01-05 20:15   ` Andy Wingo [this message]
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=87eewdu0av.fsf@pobox.com \
    --to=wingo@pobox.com \
    --cc=guile-devel@gnu.org \
    --cc=guile-users@gnu.org \
    --cc=vine35792468@gmail.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).