
Hi folks! Could anyone explain how to make the second one work as the first one? Thanks! #lang racket
(require syntax/parse
[for-syntax syntax/parse
racket/syntax-srcloc])
(define-syntax f
(syntax-parser
[(_ g a)
#`(begin
(begin-for-syntax (define b #'a))
(define-syntax (g stx)
(syntax-parse stx
[_ (quasisyntax
#,b)])))]))
(f g1 57)
(g1) ; <-- 57
#lang racket
(require syntax/parse
[for-syntax syntax/parse
racket/syntax-srcloc])
(define-syntax f
(syntax-parser
[(_ g a)
#`(begin
(begin-for-syntax (define b #'a))
(define-syntax (g stx)
(syntax-parse stx
[_ (quasisyntax/loc #'stx ; <-- difference is here
#,b)])))]))
which gives b: undefined; cannot reference an identifier before its definition in module: 'anonymous-module
It is weird to me that quasisyntax/loc
behaves differently with quasisyntax
despite what the documentation says.

(define-syntax f
(syntax-parser
[(_ g a)
(define b #'a)
#`(define-syntax (g stx)
(syntax-parse stx
[_ (quasisyntax/loc #'stx ; <-- difference is here
#,b)]))]))

In #
(… #,b …) the b is refers to a b bound at the macro definition site. Therefore the b needs to be defined either inside the syntax transformer as above.

It’s super weird that it works on the first one and not the second one

This works for me, FWIW
#lang racket
(require syntax/parse
[for-syntax syntax/parse
racket/syntax-srcloc])
(define-syntax f
(syntax-parser
[(_ g a)
#:with un (quote-syntax unsyntax)
#`(begin
(begin-for-syntax (define b #'a))
(define-syntax (g stx)
(syntax-parse stx
[_ (quasisyntax/loc stx
(un b))])))]))

Should #’stx be stx ?

(In the original)

The problem, IIUC, is that there’s a nested quasisyntax
, so if you use unsyntax
, it will pair with the wrong quasisyntax
.

Yep, I think it should be stx
too (hence my change to stx
above)

Yet another reason to use #:with
or (with-syntax ...)
instead of quasisyntax.

So, to be clear on my solution above: it fixes the unpairing error by using quote-syntax
to make unsyntax
for the syntax template.

The problem is that if I move the (define b #'a)
as @soegaard2 suggested, it won’t work for quasisyntax
(define-syntax f
(syntax-parser
[(_ g a)
(define b #'a)
#`(begin
(define-syntax (g stx)
(syntax-parse stx
[_ (quasisyntax
#,b)])))]))
b: undefined; cannot reference an identifier before its definition in module: 'anonymous-module

There’s probably a bug here, I think. The discrepancy of quasisyntax
and quasisyntax/loc
doesn’t make sense (quasisyntax/loc
looks more reasonable.)

@chenhao.zhang.rea As @sorawee that’s due to the two layers. I suggest this instead: (define-syntax f
(syntax-parser
[(_ g a)
#'(define-syntax (g stx)
(syntax-parse stx
[_
(with-syntax ([b #'a])
(syntax/loc #'stx ; <-- difference is here
b))]))]))

Or this: (define-syntax f
(syntax-parser
[(_ g a)
(with-syntax ([b #'a])
#'(define-syntax (g stx)
(syntax-parse stx
[_
(syntax/loc #'stx ; <-- difference is here
b)])))]))

Ahh. The situation is simplified to make minimal example. I just tried @sorawee approach and it works in my context. Thanks a lot both of you @soegaard2 @sorawee!

Let me spend some time to fully understand what is going on here.

So in the original version I wrote, is it true that the unsyntax
in #’b gets paired with the quasisyntax
of #(begin ...) ? I actually need that
unsyntax` to be part of the code generated by the macro, i.e. inside the syntax template.

I thought unsyntax
always pairs with the innermost layer of quasisyntax
.
