The difference between (define-for-syntax (fx x) #`(let ((x 0)) #,x)) ^-----------*
and (define-for-syntax (fy y) #`(let ((x 0)) #,y)) * is that the `x` of `(let ((x ...)))` gets lexical context from the `x` argument to `fx`, but there's no such binding for the context of `x` within `fy`. The `x` in the `let` form generated by `fx` will only bind others `x`s that also have the same context. So, it won't bind `x` passed as (fx #'x) since that `x` doesn't have the argument of `fx` in its context. To get an `x` from the inside of `fx`, you could pull it out of the result of a call to `fx`: (syntax-case (fx #'y) () [(let ([var rhs]) body) ;; #'var is `x` from the inside of `fx`: (fx #'var)]) A case could be made that the `x` of `(let ((x ...)))` shouldn't have anything to do with the `x` argument of `fx`, because they live in different phases. There's a trade-off between allowing different bindings in different phases and providing a more useful error message when a binding is accidentally used in the wrong phase. At Tue, 13 May 2014 14:44:43 +0200, "Marijn Schouten (hkBst)" wrote: > I realize this is a very old thread, but the behavior of Racket has not > changed since. > > On 03-05-14 23:29, Marijn Schouten (hkBst) wrote: > > On 07/10/2012 05:03 PM, Matthew Flatt wrote: > >> At Tue, 10 Jul 2012 10:51:57 -0400, Eli Barzilay wrote: > >>> 20 minutes ago, Marijn wrote: > >>>> > >>>> It seems to me that both these results cannot be correct > >>>> simultaneously, but I'll await the experts' opinion on that. > >>> > >>> This does look weird: > >>> > >>> #lang racket > >>> (define-for-syntax (f stx) #`(let ([x 1]) #,stx)) > >>> (define-syntax (m stx) > >>> (with-syntax ([zz (f #'x)]) #`(let ([x 2]) zz))) > >>> (m) > >>> > >>> evaluates to 1, but if I change the first two "stx" names into "x" > >>> *or* if I change the argument name for the macro to "x", then it > >>> returns 2. > >> > >> It's natural --- but not correct --- to think that #` is responsible > >> for hygiene, in which case `(f #'x)' should keep the given `x' separate > >> from the `let'-bound `x' in the result. > >> > >> Instead, hygiene is the responsibility of macro invocation, and > >> > >> #`(let ([x 1]) #,#'x) > >> > >> is simply the same as > >> > >> #`(let ([x 1]) x) > >> > >> and so > >> > >> (f #'x) > >> > >> above is equivalent to > >> > >> #`(let ([x 1]) x) > > > > IIUC then you're saying that also all the following (fx #'x) and (fy > > #'x) are equivalent to #`(let ((x 0)) x), but if you run this code then > > you will get a 0 result only for (myy), contrary to what I would expect > > based on the above explanation. > > > > #lang racket > > > > (define-for-syntax (fx x) #`(let ((x 0)) #,x)) > > (define-for-syntax (fy y) #`(let ((x 0)) #,y)) > > > > (define-syntax (mxx x) > > (syntax-case x () ((_) #`(let ((x 99)) #,(fx #'x))))) > > > > (define-syntax (mxy x) > > (syntax-case x () ((_) #`(let ((x 99)) #,(fy #'x))))) > > > > (define-syntax (myx y) > > (syntax-case y () ((_) #`(let ((x 99)) #,(fx #'x))))) > > > > (define-syntax (myy y) > > (syntax-case y () ((_) #`(let ((x 99)) #,(fy #'x))))) > > > > (mxx) > > (mxy) > > (myx) > > (myy) > > > > ==> > > > > 99 > > 99 > > 99 > > 0 > > > > Marijn > > _________________________ > > Racket Developers list: > > http://lists.racket-lang.org/dev > > _________________________ Racket Developers list: http://lists.racket-lang.org/dev