[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 =?iso-8859-1?Q?Breannd=E1n =D3 Nuall=E1in?=:
    >> >> > (let-syntax ((foo (syntax-rules () ((_ x) (bar x)))))
    >>        (define x 33))
    >> 
    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.
    >> 
    >> But surely the above `define' should not be treated as
    >> internal?

    Matthew> Are we reading the above paragraph from R5RS differently,
    Matthew> or are you suggesting that this part of R5RS is wrong? (I
    Matthew> don't consider R5RS sacred, of course.)

As a matter of fact we are.  At least, AFAICT we are.  

My (incorrect) reading of R5RS was that the top-level expression

    (let-syntax ((foo (syntax-rules () ((_ x) (bar x)))))
      (define x 33))

becomes transformed to the top-level expression

    (define x 33)

which is thus a top-level `define'.

I'm guessing that your (correct) reading of R5RS is that, in the
top-level expression,

    (let-syntax ((foo (syntax-rules () ((_ x) (bar x)))))
      (define x 33))

a `define' occurs within a `let-syntax' and so must be an internal
definition (at the start of a <body> as licensed by R5RS 5.2.2).  In
that case it should transform to something like

    (letrec ((x 33))
      )

or

    (let ()
      (define x 33))

which are both illegal because of the empty bodies.

A legal case of your (correct) reading of R5RS would be something like

    (let-syntax ((double (syntax-rules () ((_ n) (* 2 n)))))
      (define x (double 3))
      (+ x 4))

which should return 10.  The binding for `x' should be local to the
body of the `let-syntax'.

This is where my reading about R5RS was wrong.  I assumed that the
above form transformed into 

    (define x 6)
    (+ x 4)

and that these forms were then placed at top-level.

Interestingly, Chez explicitly disagrees with R5RS:

  "...let-syntax and letrec-syntax do not introduce local scopes as
  they are specified to do in the Revised5 Report.  This effect can
  easily be achieved by inserting a let around the let-syntax or
  letrec-syntax body." [Chez Scheme Users Guide, Section 4.1]

To be honest, I can't say whether I was misreading R5RS because I
never actually gave it much thought or whether the remnants of having
read CSUG a long time ago were still hanging around in my head.

Anyhow, I favour the Chez way.  It allows one to use a local piece of
syntax to generate top-level forms.  I can't think of a way to do that
with R5RS.  So, in answer to your question, I guess I don't consider
R5RS sacred either.

I'm afraid I still don't get your point about the partial-expansion
mechanism of mzscheme though.

Breanndán