[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Introductory material on hygienic macros in dr scheme
>>>>> "Matthew" == Matthew Flatt <mflatt@cs.utah.edu> writes:
Matthew> Quoting "Pierpaolo BERNARDI":
>> I have a question myself on macros. mzscheme 200alpha9 gives:
>>
>> > (let-syntax ((foo (syntax-rules () ((_ x) (bar x)))))
>> (define x 33))
>>
>> begin (possibly implicit): no expression after a sequence of
>> internal definitions in: ((define x 33))
>>
>> While the same expression works in Chez, where the (define x
>> ...) is considered top level.
>>
>> From reading the r5rs is not clear to me which behaviour is
>> correct.
Matthew> In the "internal definitions" section:
Matthew> Definitions may occur at the beginning of a <body> (that
Matthew> is, the body of a lambda, let, let*, letrec, let-syntax,
Matthew> or letrec-syntax expression or that of a definition of an
Matthew> appropriate form). Such definitions are known as internal
Matthew> definitions as opposed to the top level definitions
Matthew> described above.
Matthew> So it seems the `define' above has to be treated as an
Matthew> internal definition. But I wouldn't bet against there
Matthew> being a contradictory statement elsewhere in R5RS.
But surely the above `define' should not be treated as internal? At
most it should be treated as a `define' inside a top-level `begin' as
given in Section 5.1 of R5RS:
"At the top level of a program (begin <form1> ...) is equivalent to
the sequence of expressions, definitions, and syntax definitions that
form the body of the begin."
This seems to be what mzscheme is trying to do: wrap it in an implicit
`begin' only then to grumble that the `define' appears in a `begin'
with no further expressions.
Matthew> The Chez model seems to it interact confusingly
Matthew> (wrongly?) with internal definitions. Here's the simplest
Matthew> example that I could manage:
Matthew> (let-syntax ([ack
Matthew> (syntax-rules ()
Matthew> [(_) 'outer-ack])])
Matthew> (letrec-syntax ([foo
Matthew> (syntax-rules ()
Matthew> ((_ x) (define (x) (bar))))]
Matthew> [bar
Matthew> (syntax-rules ()
Matthew> ((_) (ack)))]) ;; <<<<<
Matthew> (foo x))
Matthew> (define (ack) 'inner-ack)
Matthew> (x))
Matthew> Which `ack' is the one marked by "<<<<<" ? If the
Matthew> `letrec-syntax' expression produces a definition, then we
Matthew> have a two-definition internal sequence, and `(define
Matthew> (ack) 5)' should bind the marked `ack'. In other words,
Matthew> the above should be equivalent to
Matthew> (let-syntax ([ack
Matthew> (syntax-rules ()
Matthew> [(_) 'outer-ack])])
Matthew> (letrec ([x
Matthew> (letrec-syntax ([bar
Matthew> (syntax-rules ()
Matthew> ((_) (ack)))])
Matthew> (lambda () (bar)))]
Matthew> [ack (lambda () 'inner-ack)])
Matthew> (x)))
Matthew> However, Chez produces 'outer-ack for the first
Matthew> expression, and 'inner-ack for the second. So the marked
Matthew> `ack' is actually captured by the outer `ack', not not
Matthew> the internal definition.
Is this really right? As I see it, the syntax transformations on
(foo x) should be:
(foo x) => (define (x) (bar))
=> (define (x) (ack))
=> (define (x) 'outer-ack)
so the entire form transforms to
(define (x) 'outer-ack)
(define (ack) 'inner-ack)
(x)
and then evaluates to outer-ack, as done by Chez. Or am I (and Chez)
missing something here?
Generally, I'm inclined to trust Chez as the only fully watertight
implementation of syntax extension.
Going back to the initial question concerning Mzscheme's rejection of
(let-syntax ((foo (syntax-rules ()
((_ x) (bar x)))))
(define x 33))
I would expect this to transform to (define x 33) without any problem.
Regards,
Breanndán