[racket] define-syntax vs let-syntax

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Tue Nov 16 14:54:17 EST 2010

On 11/16/2010 12:45 PM, Jon Rafkind wrote:
> `define-syntax' has different behavior from `let-syntax' when the
> transformer operates on top-level bindings in the transformer environment.
>
> (define-for-syntax foo 1)
>
> (define-syntax (x1 stx)
>   (printf "z: foo is ~a\n" foo)
>   (set! foo (add1 foo))
>   (printf "z: foo is ~a\n" foo)
>   #'1)
>
> (x1)
>
> #;
> (let-syntax ([x1 (lambda (stx)
>                    (printf "z: foo is ~a\n" foo)
>                    (set! foo (add1 foo))
>                    (printf "z: foo is ~a\n" foo)
>                    #'1)])
>   (x1))
>
> With `define-syntax' I see
> z: foo is 1
> z: foo is 2
>
> But with `let-syntax' I see
> z: foo is 1
> z: foo is 1
>
> Is this a bug or am I missing something?
I guess it has to do with expansion order somehow. If I try to
interleave calls to a macro defined by `define-syntax' and the
`let-syntax' expression I see the `define-syntax' expansions happen first.

(define-for-syntax foo 1)

(define-syntax (x2 stx)
  (printf "z: foo is ~a\n" foo)
  (set! foo (add1 foo))
  (printf "z: foo is ~a\n" foo)
  #'1)
(x2)
(let-syntax ([x1 (lambda (stx)
                   (printf "let z: foo is ~a\n" foo)
                   (set! foo (add1 foo))
                   (printf "let z: foo is ~a\n" foo)
                   #'1)])
  (x1))

(x2)

z: foo is 1
z: foo is 2
z: foo is 2
z: foo is 3
let z: foo is 3
let z: foo is 3


Posted on the users mailing list.