[plt-scheme] Identifier macro assignment: syntax-id-rules vs. syntax-case

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Jan 13 18:30:12 EST 2007

At Thu, 11 Jan 2007 06:06:13 -0800, Casey Klein wrote:
> I tried naively to translate the language manual's `pwd' macro
> (section 12.1) from the syntax-id-rules form to syntax-case:
> 
>    (define-syntax (pwd stx)
>      (syntax-case stx (set!)
>        [(set! pwd expr) #'(current-directory expr)]
>        [(pwd expr ...) #'((current-directory) expr ...)]
>        [pwd #'(current-directory)]))
> 
> Rather than expanding according to the first case, the expression 
> (set! pwd "/tmp") tries to mutate the `pwd' binding. Why doesn't this
> happen when the macro's defined with syntax-id-rules?

When an identifier like `pwd' is bound to a procedure, then the macro
expander only calls the procedure when the identifier is used by itself
or in an "application" position.

To tell the macro expander to call the transformer procedure when the
identifier is the target of a `set!', you need to wrap the procedure
with `make-set!-transformer':

   (define-syntax pwd
     (make-set!-transformer
      (lambda (stx)
        (syntax-case stx (set!)
          [(set! pwd expr) #'(current-directory expr)]
          [(pwd expr ...) #'((current-directory) expr ...)]
          [pwd #'(current-directory)]))))


That's what the `syntax-id-rules' macro does:

 > (syntax-rules ())
 #<procedure>
 > (syntax-id-rules ())
 #<set!-transformer>


Matthew



Posted on the users mailing list.