[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