Previous: , Up: stdlib syntax-case   [Index]


5.12.11 Common Lisp style macros

Using datum->syntax, it is even possible to break hygiene entirely and write macros in the style of old Lisp macros. The lisp-transformer procedure defined below creates a transformer that converts its input into a datum, calls the programmer’s procedure on this datum, and converts the result back into a syntax object scoped where the original macro use appeared:

(define (lisp-transformer proc)
  (lambda (stx)
    (syntax-case stx ()
      ((key . rest)
       (datum->syntax #'key (proc (syntax->datum stx)))))))

This transformer can be used as follows, first create a library with the definition in it:

(library (lisp-trans)
  (export lisp-transformer)
  (import (rnrs))

  (define (lisp-transformer proc)
    (lambda (stx)
      (syntax-case stx ()
        ((key . rest)
         (datum->syntax #'key (proc (syntax->datum stx))))))))

then import the library for the ‘expand’ phase; the following example shows what is handed to the client procedure:

(import (rnrs)
  (for (lisp-trans) expand))

(define-syntax print-it
  (lisp-transformer (lambda (thing)
                      (write thing)
                      (newline)
                      #f)))

(print-it (1 2 3))
-| (print-it (1 2 3))

notice that the macro use prints the value of thing, then returns #f which is evaulated in place of the macro use and the result is #f itself.

Now we shold understand the following:

(import (rnrs)
  (for (lisp-trans) expand))

(define-syntax even
  (lisp-transformer
    (lambda (thing)
      `(begin
         (write (quote ,(map even? (cadr thing))))
         (newline)))))

(even (1 2 3))
-| (#f #t #f)

the macro use (even (1 2 3)) is equivalent to:

(begin
  (write (quote (#f #t #f)))
  (newline))

that is, the form returned by the client procedure is evaluated in place of the macro use.


Previous: , Up: stdlib syntax-case   [Index]