[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Libraries and repositories

Paul Graham wrote:

> If it's only a couple lines, could you send us a def of
> defmacro in terms of syntax-case?

Eli Barzilay posted this to the PLT Scheme discussion list a few weeks 

  (define-syntax (define-macro stx)
    (syntax-case stx ()
     ((_ (macro . args) . body)
      (syntax (define-macro macro (lambda args . body))))
     ((_ macro transformer)
       (define-syntax (macro stx2)
         (let ((v (syntax-object->datum stx2)))
            (apply transformer (cdr v)))))))))

In short, it's a macro-defining macro.  The point is, why settle for
DEFINE-MACRO?  With this, you can create your own macro-defining macro
notation.  You can't add hygiene after the fact, so this gives you the 
choice of using it if you want it.

I had posted some Arc macros using SYNTAX-CASE (I've elided some easy
but inessential rules):

  (define-syntax (arc-if expr)
    (syntax-case expr ()
      [(_ test then else)
       (with-syntax ([it-id (implicit-identifier (syntax test) 'it)])
         (syntax (let ([it-id test])
                   (if it-id then else))))]))

  (define-syntax (arc-and expr)
    (syntax-case expr ()
      [(_)                (syntax #t)]
      [(_ first)          (syntax first)]
      [(_ first rest ...) (syntax (arc-if first (arc-and rest ...) #f))]))

In response, to test his definition, Eli wrote:

  (define-macro (arc-if test true false)
    (let ((x (gensym)))
      `(let ((it ,test))
         (if it ,true ,false))))

  (define-macro (arc-and . args)
    (cond ((null? args) #t)
          ((null? (cdr args)) (car args))
          (else `(arc-if ,(car args) (arc-and ,@(cdr args)) #f))))

In case anyone wonders what's interesting about these, it's that they
bind the identifier IT automatically.

(I'm glossing over some scoping issues here, but those would lead us
far astray of this list.)