emacs-bug-tracker
[Top][All Lists]
Advanced

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

[debbugs-tracker] bug#10099: closed (Null (begin) blocks - V2.0.3 report


From: GNU bug Tracking System
Subject: [debbugs-tracker] bug#10099: closed (Null (begin) blocks - V2.0.3 reports error was OK in V2.0.2)
Date: Thu, 22 Dec 2011 01:20:02 +0000

Your message dated Wed, 21 Dec 2011 20:17:47 -0500
with message-id <address@hidden>
and subject line Re: bug#10099: Null (begin) blocks - V2.0.3 reports error was 
OK in V2.0.2
has caused the debbugs.gnu.org bug report #10099,
regarding Null (begin) blocks - V2.0.3 reports error was OK in V2.0.2
to be marked as done.

(If you believe you have received this mail in error, please contact
address@hidden)


-- 
10099: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=10099
GNU Bug Tracking System
Contact address@hidden with problems
--- Begin Message --- Subject: Re: Null (begin) blocks - V2.0.3 reports error was OK in V2.0.2 Date: Tue, 22 Nov 2011 00:02:35 +0100 User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)
Hi Ian!

In the future, please include address@hidden in bug reports.  It
creates a ticket so we don't forget.  The system changed a bit recently,
but we hope that it works OK for you.  It's certainly working better for
us.

Anyway:

On Mon 21 Nov 2011 18:25, Ian Hulin <address@hidden> writes:

> (define-public (void? x) (eq? x (begin)))

This is really not right, if I understand what you are checking for.
These will work:

  (define-public (void? x) (unspecified? x))
  (define-public (void? x) (eq? x *unspecified*))
  (define-public (void? x) (eqv? x *unspecified*))
  (define-public (void? x) (eq? x (if #f #f))

> This works in V1.8, and apparently used to work in 2.0.2 (no errors),
> but in 2.0.3
> (begin) is OK at the repl, (with readline enabled and activated), but
> in any sort of procedure using it causes a diagnostic, reporting
> either at the repl or in .scm files,
>
> xxx: source expression failed to match any pattern in form (begin).

Interesting.  If it changed incompatibly in 2.0.x, that is a Guile bug.
Sorry about that!  We'll fix it.

That said, though, you have a few misunderstandings here.

> 6.13.1 Evaluating a series of expressions
> <snip>
> — syntax: begin expr1 expr2 ...

First of all, this documentation is not quite correct.  Since R5RS there
have been *two* kinds of begins: one that splices and one that
sequences.

I know that sounds complicated, but let me explain.  It's not widely
known, and many Schemers consider it to be something of a bug that they
both share the same name.

Scheme has two contexts: definition context and expression context.
Like, you can only put nested definitions at the top of a function,
before the expressions, and a function has to end with an expression.

`Begin' in definition context "splices" its subforms into its containing
form.  This is to allow macros to expand to multiple definitions.
In definition context, `begin' is just syntactic.

`Begin' in expression context evaluates its subforms in order.  It is
used for its semantic property of sequencing effects.

It is possible for a `begin' in definition context to have no subforms.
But in expression context, you need an expression, and if there are no
expressions to evaluate, the result is a syntactic error.  That is what
you are running into.

>     Guile also allows the expression (begin), a begin with no
> sub-expressions. Such an expression returns the `unspecified' value.

So, I guess we have to fix this in 2.0.x.  This behavior will probably
not be available in 2.2, however, so it's best to change your code now,
at the same time that we fix Guile to have the old behavior (and fix the
docs).

Finally, we are considering having expressions that produce unspecified
values actually produce 0 values.  So, for example, (if #f #f) would be
the same as (values).  Of course it's not something we can do in 2.0,
and we would try to publicise it well, but do keep it in mind.

Regards,

Andy
-- 
http://wingolog.org/



--- End Message ---
--- Begin Message --- Subject: Re: bug#10099: Null (begin) blocks - V2.0.3 reports error was OK in V2.0.2 Date: Wed, 21 Dec 2011 20:17:47 -0500 User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)
Hi,

On Wed 23 Nov 2011 07:27, Andy Wingo <address@hidden> writes:

> On Tue 22 Nov 2011 00:02, Andy Wingo <address@hidden> writes:
>>On Mon 21 Nov 2011 18:25, Ian Hulin <address@hidden> writes:
>>> (define-public (void? x) (eq? x (begin)))
>>> This works in V1.8, and apparently used to work in 2.0.2 (no errors),
>>
>> Interesting.  If it changed incompatibly in 2.0.x, that is a Guile bug.
>> Sorry about that!  We'll fix it.
>
> I cannot reproduce this issue with 2.0.2.  I suspect that this code has
> been this way since early 1.9 releases, and is a consquence of switching
> to the new syntax expander.
>
> That said, this change was not mentioned in NEWS, and the documentation
> has not been updated, so perhaps we should do something.  I would prefer
> just to leave it as it is, unless you think that adding a compatibility
> hack could help you somehow.  What do you think, Ian?

I have appended the updated documentation to this reply to clarify that
(begin) in expression context is invalid syntax.  I have also added a
backwards-compatibility shim to issue a deprecation warning and
translate it to *unspecified*, in Guile 2.0.  That should fix this bug.

Regards,

Andy


6.13.1 Sequencing and Splicing
------------------------------

As an expression, the `begin' syntax is used to evaluate a sequence of
sub-expressions in order.  Consider the conditional expression below:

     (if (> x 0)
         (begin (display "greater") (newline)))

   If the test is true, we want to display "greater" to the current
output port, then display a newline.  We use `begin' to form a compound
expression out of this sequence of sub-expressions.

 -- syntax: begin expr1 expr2 ...
     The expression(s) are evaluated in left-to-right order and the
     value of the last expression is returned as the value of the
     `begin'-expression.  This expression type is used when the
     expressions before the last one are evaluated for their side
     effects.

   The `begin' syntax has another role in definition context (*note
Internal Definitions::).  A `begin' form in a definition context
"splices" its subforms into its place.  For example, consider the
following procedure:

     (define (make-seal)
       (define-sealant seal open)
       (values seal open))

   Let us assume the existence of a `define-sealant' macro that expands
out to some definitions wrapped in a `begin', like so:

     (define (make-seal)
       (begin
         (define seal-tag
           (list 'seal))
         (define (seal x)
           (cons seal-tag x))
         (define (sealed? x)
           (and (pair? x) (eq? (car x) seal-tag)))
         (define (open x)
           (if (sealed? x)
               (cdr x)
               (error "Expected a sealed value:" x))))
       (values seal open))

   Here, because the `begin' is in definition context, its subforms are
"spliced" into the place of the `begin'.  This allows the definitions
created by the macro to be visible to the following expression, the
`values' form.

   It is a fine point, but splicing and sequencing are different.  It
can make sense to splice zero forms, because it can make sense to have
zero internal definitions before the expressions in a procedure or
lexical binding form.  However it does not make sense to have a
sequence of zero expressions, because in that case it would not be
clear what the value of the sequence would be, because in a sequence of
zero expressions, there can be no last value.  Sequencing zero
expressions is an error.

   It would be more elegant in some ways to eliminate splicing from the
Scheme language, and without macros (*note Macros::), that would be a
good idea.  But it is useful to be able to write macros that expand out
to multiple definitions, as in `define-sealant' above, so Scheme abuses
the `begin' form for these two tasks.


-- 
http://wingolog.org/


--- End Message ---

reply via email to

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