[racket-dev] some surprising behavior with syntax-parameterize and lexical info
On 04/06/2012 12:47 PM, Danny Yoo wrote:
>>> I suspect that I should be using quote-syntax at this specific point,
>>> but I am not completely sure.
>>
>> Right. Try replacing ??? with (quote-syntax #,a-placeholder).
>
>
> I have to admit that I'm still confused. Here's my example:
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> #lang racket
>
> (require racket/stxparam racket/splicing)
>
> (define-syntax-parameter current-def #f)
>
> (define-syntax (def stx)
> (syntax-case stx ()
> [(_ (name args ...) body ...)
> (with-syntax ([function-stx stx])
> (syntax/loc stx
> (define (name args ...)
> (splicing-syntax-parameterize ([current-def
> (quote-syntax
> function-stx)])
> body ...))))]))
You moved the 'splicing-syntax-parameterize' back inside the scope of
'args'. That's why it doesn't work. Here's the correct version:
(define-syntax (def stx)
(syntax-case stx ()
[(_ (name args ...) body ...)
(with-syntax ([function-stx stx])
(syntax/loc stx
(splicing-syntax-parameterize
([current-def (quote-syntax function-stx)])
(define (name args ...)
body ...))))]))
> From what I understand of quote-syntax, it should create a syntax
> object that preserves the lexical information in function-stx.
> function-stx should be a syntax object whose lexical information does
> not include the function argument's variables. Yet, when I run this,
> the program prints 4, rather than 84 as I expected.
At the time 'def' is expanded, the lexical context of 'function-stx'
does not include the bindings of 'args'. But then the macro produces an
expression with that term inside a 'quote-syntax' form that is inside
the scope of the 'args'. So by the time the expander gets to the
'quote-syntax' form, the lexical context of the original term has been
enriched with the 'args' bindings.
In other words, the appearance of 'quote-syntax' in a macro template
doesn't magically freeze the lexical context of its argument then and
there. What matters is the lexical context when the expander reaches the
'quote-syntax' expression itself.
That's why (quote-syntax function-stx) needs to go outside the binding
of the 'args'.
(There are tricks (eg, 3D syntax or syntax properties) that can hide the
syntax from the expander so it doesn't get the 'args' wraps, but they're
fragile. And hacky. Don't use them.)
Ryan