Prev Up Next

Users can create their own special forms by defining macros. A macro is a symbol that has a transformer procedure associated with it. When Scheme encounters a macro-expression -- ie, a form whose head is a macro -- , it applies the macro's transformer to the subforms in the macro-expression, and evaluates the result of the transformation.

Ideally, a macro specifies a purely textual transformation from code text to other code text. This kind of transformation is useful for abbreviating an involved and perhaps frequently occurring textual pattern.

A macro is defined using the special form define-macro (but see sec R.4). For example, if your Scheme lacks the conditional special form when, you could define when as the following macro:

(define-macro when
  (lambda (test . branch)
    (list 'if test
      (cons 'begin branch))))

This defines a when-transformer that would convert a when-expression into the equivalent if-expression. With this macro definition in place, the when-expression

(when (< (pressure tube) 60)
   (open-valve tube)
   (attach floor-pump tube)
   (depress floor-pump 5)
   (detach floor-pump tube)
   (close-valve tube))

will be converted to another expression, the result of applying the when-transformer to the when-expression's subforms:

(apply
  (lambda (test . branch)
    (list 'if test
      (cons 'begin branch)))
  '((< (pressure tube) 60)
      (open-valve tube)
      (attach floor-pump tube)
      (depress floor-pump 5)
      (detach floor-pump tube)
      (close-valve tube)))

The transformation yields the list

(if (< (pressure tube) 60)
    (begin
      (open-valve tube)
      (attach floor-pump tube)
      (depress floor-pump 5)
      (detach floor-pump tube)
      (close-valve tube)))

Scheme will then evaluate this expression, as it would any other.

As an additional example, here is the macro-definition for when's counterpart unless:

(define-macro unless
  (lambda (test . branch)
    (list 'if
          (list 'not test)
          (cons 'begin branch))))

Alternatively, we could invoke when inside unless's definition:

(define-macro unless
  (lambda (test . branch)
    (cons 'when
          (cons (list 'not test) branch))))

Macro expansions can refer to other macros.

Prev Up Next

Y'know, if you log in, you can write something here, or contact authors directly on the site. Create a New User if you don't already have an account.