chenhao.zhang.rea
2021-12-17 16:10:03

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.


soegaard2
2021-12-17 16:25:10

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


soegaard2
2021-12-17 16:26:39

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.


sorawee
2021-12-17 16:27:37

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


sorawee
2021-12-17 16:28:07

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))])))]))


soegaard2
2021-12-17 16:28:50

Should #’stx be stx ?


soegaard2
2021-12-17 16:29:02

(In the original)


sorawee
2021-12-17 16:29:11

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


sorawee
2021-12-17 16:29:41

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


soegaard2
2021-12-17 16:30:19

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


sorawee
2021-12-17 16:32:05

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


chenhao.zhang.rea
2021-12-17 16:33:57

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


sorawee
2021-12-17 16:35:57

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


soegaard2
2021-12-17 16:36:35

@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))]))]))


soegaard2
2021-12-17 16:37:19

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)])))]))


chenhao.zhang.rea
2021-12-17 16:46:12

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!


chenhao.zhang.rea
2021-12-17 16:47:19

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


chenhao.zhang.rea
2021-12-17 16:49:39

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 thatunsyntax` to be part of the code generated by the macro, i.e. inside the syntax template.


chenhao.zhang.rea
2021-12-17 16:50:38

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


sorawee
2021-12-17 16:55:40