<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Another thing about this, if the definition produced by the macro is
    instead generated by the `make-transformer' macro then it will have
    the wrong number of marks on it when everything is finally expanded.
    `syntax-local-introduce' fixes this by essentially removing that
    extra mark.<br>
    <br>
    <meta http-equiv="content-type" content="text/html;
      charset=ISO-8859-1">
    <pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; word-wrap: break-word; white-space: pre-wrap; ">#lang racket

(require (for-meta 0 racket/splicing)
         (for-meta 1 syntax/parse)
         (for-meta 2 syntax/parse
                     racket/base))

(begin-for-syntax
  (define-syntax (make-transformer stx)
    (syntax-parse stx
      [(_ name (pattern ...) action)
       #'(quote-syntax (define-syntax name
             (lambda (stx) ;; HERE change to #'(quote-syntax
               (syntax-parse stx
                 [(_ pattern ...) action]))))])))

(define-syntax (macro-generator stx)
  (syntax-parse stx
    [(_ name pattern action)
     #'(splicing-let-syntax
         ([make (lambda (stx)
                  (syntax-parse stx
                    [(_)
                     (syntax-local-introduce
                       (make-transformer name pattern action))]))])
         (make))]))

(macro-generator foo (x ...) #'(list x ...))
(foo 1 2 3)</pre>
    <br>
    The `name' passed as an argument to `make-transformer' will not have
    the mark applied to it by the transformer in the
    splicing-let-syntax, so the resulting define-syntax form will use a
    different 'foo' from the one passed to `macro-generator'. Using
    `syntax-local-introduce' applies the mark that was used when
    `(make)' was expanded thus removing all marks from the final
    expansion.<br>
    <br>
    On 06/01/2012 12:16 PM, Jon Rafkind wrote:
    <blockquote cite="mid:4FC906FE.4040406@cs.utah.edu" type="cite">
      <meta http-equiv="content-type" content="text/html;
        charset=ISO-8859-1">
      <meta http-equiv="content-type" content="text/html;
        charset=ISO-8859-1">
      <pre style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; word-wrap: break-word; white-space: pre-wrap; ">Today's macro PSA is about macro-generating-macro forms. If you use a macro to generate a transformer then you must be careful about nesting `syntax' forms otherwise you will interpolate templates too many times. Specifically #'#'x will interpolate x twice. Given the following bindings:

  chicken = (syntax (egg ...))
  pattern = (syntax chicken)

The problem is if an additional `syntax' is wrapped around `pattern'. After one interpolation of `syntax' we will have

  (syntax (egg ...))

At which point `egg' had better be bound as a pattern variable otherwise interpolation will fail.

To work around this problem the `quote-syntax' form should be used:

  #'(quote-syntax pattern)

which prevents the (syntax (egg ...)) layer from being interpolated because `quote-syntax' does not do interpolation.

The following example demonstrates the issue. On the line 'HERE' the inner syntax should be `quote-syntax' otherwise the following error is produced

  x.rkt:27:24: syntax: no pattern variables before ellipses in template at: ... in: (_ x ...)

To be fair this issue only comes up because I used `make-transformer' in the body of a phase 2 function so the output of `make-transformer' had to have two levels of syntax, because its a macro that should ultimately evaluate to a syntax form. A simpler solution would have been to do

  #'(define-syntax name (make-transformer pattern action))

So that `make-transformer' only had to return one level of syntax. But anyway I got into this situation for other reasons.

#lang racket

(require (for-meta 0 racket/splicing)
         (for-meta 1 syntax/parse)
         (for-meta 2 syntax/parse
                     racket/base))

(begin-for-syntax
  (define-syntax (make-transformer stx)
    (syntax-parse stx
      [(_ (pattern ...) action)
       #'#'(lambda (stx) ;; HERE change to #'(quote-syntax
             (syntax-parse stx
               [(_ pattern ...) action]))])))

(define-syntax (macro-generator stx)
  (syntax-parse stx
    [(_ name pattern action)
     #'(splicing-let-syntax
         ([make (lambda (stx)
                  (syntax-parse stx
                    [(_ name)
                     (with-syntax ([transformer (make-transformer pattern action)])
                       #'(define-syntax name transformer))]))])
         (make name))]))

(macro-generator foo (x ...) #'(list x ...))
(foo 1 2 3)</pre>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">____________________
  Racket Users list:
  <a class="moz-txt-link-freetext" href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>