Hi, On Wed 23 Nov 2011 07:27, Andy Wingo <wi...@pobox.com> writes:
> On Tue 22 Nov 2011 00:02, Andy Wingo <wi...@pobox.com> writes: >>On Mon 21 Nov 2011 18:25, Ian Hulin <i...@hulin.org.uk> 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/