[R6RS] syntax-case semantics

dyb at cs.indiana.edu dyb at cs.indiana.edu
Fri Mar 17 01:41:31 EST 2006


> SRFI 72's modified hygiene rule appears to address a real 
> hygiene-related issue.  If the R6RS syntax-case specification is not 
> going to address that issue, we should have a rationale for that.

The essential difference boils down to whether identifiers with the same
name in two different syntax forms used to construct a macro's output are
considered the same.  With the traditional syntax-case semantics, they
are; with SRFI 72, they aren't.  So if I write:

  (define-syntax case
    (lambda (x)
      (define process-clause
        (lambda (clauses)
          (syntax-case clauses (else)
            [() #'()]
            [([else e1 e2 ...]) #'([else e1 e2 ...])]
            [([(k ...) e1 e2 ...] m ...)
             (with-syntax ([(m ...) (process-clause #'(m ...))])
               #'([(memv t '(k ...)) e1 e2 ...] m ...))])))
      (syntax-case x ()
        [(_ expr case-clause ...)
         (with-syntax ([(cond-clause ...) (process-clause #'(case-clause ...))])
           #'(let ([t expr])
               (cond cond-clause ...)))])))

using the traditional syntax-case semantics, the introduced binding for
t captures the introduced references for t.  With the SRFI 72 semantics,
it doesn't, and I'd have to write instead:

  (define-syntax case
    (lambda (x)
      (define process-clause
        (lambda (t clauses)
          (with-syntax ([t t])
            (syntax-case clauses (else)
              [() #'()]
              [([else e1 e2 ...]) #'([else e1 e2 ...])]
              [([(k ...) e1 e2 ...] m ...)
               (with-syntax ([(m ...) (process-clause #'t #'(m ...))])
                 #'([(memv t '(k ...)) e1 e2 ...] m ...))]))))
      (syntax-case x ()
        [(_ expr case-clause ...)
         (with-syntax ([t #'t])
           (with-syntax ([(cond-clause ...)
                          (process-clause #'t #'(case-clause ...))])
             #'(let ([t expr])
                 (cond cond-clause ...))))])))

Whether there's a hygiene issue here is debatable.  I say there's not one,
because in my mind, hygiene issues involve interactions between macros,
not within a single macro.  Hygienic macro expanders enable me to write
lexically scoped macros, i.e., macros that don't accidentally capture
references in their context of invocation or have their references
accidentally captured by bindings in their context of invocation, and I
can do so equally well with either semantics.

While the SRFI 72 semantics is slightly simpler, the traditional semantics
is easier to work with.  (There is a tacit admission of this fact in the
SRFI exception that commonizes identifiers in unquoted nested quasisyntax
forms.)  I might buy the "hygiene issue" or whatever you want to call it if
I had ever run into it or seen anyone else run into it, but I haven't.  So
I prefer the traditional semantics.

Kent



More information about the R6RS mailing list