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

Re: Introductory material on hygienic macros in dr scheme



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.

In the "internal definitions" section:

 Definitions may occur at the beginning of a <body> (that is, the body
 of a lambda, let, let*, letrec, let-syntax, or letrec-syntax expression
 or that of a definition of an appropriate form). Such definitions are
 known as internal definitions as opposed to the top level definitions
 described above.

So it seems the `define' above has to be treated as an internal
definition. But I wouldn't bet against there being a contradictory
statement elsewhere in R5RS.

I think the Chez convention probably doesn't work for PLT Scheme --
long explanation below.

Matthew

------------------------------

The Chez model seems to it interact confusingly (wrongly?) with
internal definitions. Here's the simplest example that I could manage:

(let-syntax ([ack
	      (syntax-rules ()
		[(_) 'outer-ack])])
  (letrec-syntax ([foo
		   (syntax-rules ()
		     ((_ x) (define (x) (bar))))]
		  [bar
		   (syntax-rules ()
		     ((_) (ack)))]) ;; <<<<<
    (foo x))
  (define (ack) 'inner-ack)
  (x))

Which `ack' is the one marked by "<<<<<" ? If the `letrec-syntax'
expression produces a definition, then we have a two-definition
internal sequence, and `(define (ack) 5)' should bind the marked `ack'.
In other words, the above should be equivalent to

 (let-syntax ([ack
	      (syntax-rules ()
		[(_) 'outer-ack])])
  (letrec ([x
	    (letrec-syntax ([bar
			     (syntax-rules ()
			       ((_) (ack)))])
	      (lambda () (bar)))]
	   [ack (lambda () 'inner-ack)])
    (x)))

However, Chez produces 'outer-ack for the first expression, and
'inner-ack for the second. So the marked `ack' is actually captured by
the outer `ack', not not the internal definition.

Scale this up to the problem of definitions with `class' and `unit',
consider that `define-struct' generates both normal and syntax
definitions, etc., and I believe the above pattern will soon cause
problems in practice.