bug-guile
[Top][All Lists]
Advanced

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

bug#10099: Null (begin) blocks - V2.0.3 reports error was OK in V2.0.2


From: Andy Wingo
Subject: 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/





reply via email to

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