From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Andy Wingo Newsgroups: gmane.lisp.guile.devel Subject: Re: GNU Guile 2.9.5 Released [beta] Date: Sun, 05 Jan 2020 21:15:52 +0100 Message-ID: <87eewdu0av.fsf@pobox.com> References: <87lfs8kkao.fsf@pobox.com> <20191201204142.0388791e61fa443e615605da@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="192880"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) Cc: Andy Wingo , guile-users@gnu.org, guile-devel@gnu.org To: Chris Vine Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Sun Jan 05 21:16:18 2020 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1ioCJt-000o1e-Mi for guile-devel@m.gmane.org; Sun, 05 Jan 2020 21:16:17 +0100 Original-Received: from localhost ([::1]:44978 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ioCJs-00076a-I8 for guile-devel@m.gmane.org; Sun, 05 Jan 2020 15:16:16 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:53344) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ioCJn-00074n-C8 for guile-devel@gnu.org; Sun, 05 Jan 2020 15:16:13 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ioCJj-0005aa-UD for guile-devel@gnu.org; Sun, 05 Jan 2020 15:16:10 -0500 Original-Received: from fanzine.igalia.com ([178.60.130.6]:59226) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ioCJj-0005Zd-0g for guile-devel@gnu.org; Sun, 05 Jan 2020 15:16:07 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID:In-Reply-To:Date:References:Subject:Cc:To:From; bh=YZBQM9PCZYl/BWPSO3Ym16NT7AXrHemZk6pt0kSpE1c=; b=EzevglsCeJ/Pevhz488CVLqLih4BzJquEQ0dywV93WY1d64AG1GxxsV2Vsv9CB37zdsAB2eKQlOg0GOKUFKkRWylF8x2rRea5CpqIufEm9M5HDTcLGTj5hX2GUCkD5KjwKaAPg+3qiqOiAJRuE1b9g1ICacCFeTUzeftvjbRbSHbtQGffBmoJGaBAdwggdFYSN2iwR5is8QBQECfbyCBC025gP5FvZoLWA5gA/acPF26wNti4EMA7AKwEWQ/RnLZ896wsJF11Dyeva4woFze5sh1tR2Esb1Ju04v8Ng5YM+JeBZjjQ7ypjMLHiLfewUnZAaJltSVp7XqLxSfb91Syw==; Original-Received: from [88.123.12.110] (helo=sparrow) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1ioCJe-0001Tv-DG; Sun, 05 Jan 2020 21:16:02 +0100 In-Reply-To: <20191201204142.0388791e61fa443e615605da@gmail.com> (Chris Vine's message of "Sun, 1 Dec 2019 20:41:42 +0000") X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 178.60.130.6 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.org gmane.lisp.guile.devel:20226 Archived-At: On Sun 01 Dec 2019 21:41, Chris Vine 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 =C2=A77.1 of the standard library at > http://www.r6rs.org/r6rs-errata.html, and for R7RS without corrigendum > (at =C2=A74.2.7 and =C2=A77.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