[plt-scheme] Introducing an Identifier into the Lexical Context of a Macro Call

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Wed Oct 13 14:06:42 EDT 2004

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



Posted on the users mailing list.