[plt-scheme] Introducing an Identifier into the Lexical Context of a Macro Call
At Tue, 12 Oct 2004 13:51:49 -0700, "Williams, M. Douglas" wrote:
> (define-syntax (if-it stx)
> (syntax-case stx ()
> [(src-if-it test then else)
> (syntax-case (datum->syntax-object (syntax src-if-it) 'it) ()
> [it (syntax (let ([it test]) (if it then else)))])])))
> (if-it (memq 'b '(a b c)) it 'nope) ; => '(b c)
>
> ---
>
> Is this the best way to introduce an identifier ('it' in this case) into the
> lexical context of the macro's use?
In version 299, I recommend the following alternative:
(require (lib "stxparam.ss"))
(require-for-syntax (lib "stxparam.ss"))
;; This should be private to the `if-it' and `it' macros:
(define-syntax-parameter it-param
(lambda (stx) (raise-syntax-error #f "use of keyword out of context" stx)))
;; Export as public:
(define-syntax it
(make-parameter-rename-transformer #'it-param))
;; Export as public:
(define-syntax if-it
(syntax-rules ()
[(_ test then else)
(let ([it-v test])
(syntax-parameterize ([it-param (make-rename-transformer #'it-v)])
(if it-v then else)))]))
In this case, `if-it' does not introduce the `it' binding (i.e., the
macro is hygienic). Instead, it merely adjusts the meaning of `it'
within the `if-it' form.
But that's too much code. Someone should look for a nice way to package
this pattern of `define-syntax-paarameter',
`make-parameter-rename-transformer', `syntax-parameterize' and
`make-rename-transformer'. Maybe it would be a
`define-syntax-with-keywords' form that looks something like this:
;; Binds `if-it' and `it':
(define-syntax-with-keywords if-it (it)
(syntax-rules ()
[(_ test then else)
(let ([it-v test])
(with-keyword-redirect ([it it-v])
(if it-v then else)))]))
Or maybe there's something more general but still convenient.
Matthew