LispWorks User Guide and Reference Manual > 28 The COMPILER Package




Defines a function that computes the expansion of a form.




deftransform name transform-name lambda-list &body body => list-of-transforms



A symbol naming the function to which the transform is to be applied.


The symbol naming the transformation -- it should be unique for the function being transformed -- and provides a handle with which to redefine an existing transform.


This must match against the form being expanded before expansion is allowed to take place, in the sense that it must be valid to call a function with such a lambda list using the arguments supplied in the candidate-form for expansion.


The body of the expander function, the result of which replaces the original form (unless it evaluates to compiler::%pass% , in which case no transformation is applied).



A list of the names of transforms defined for the function, including the one just added.


deftransform , like defmacro , defines a function that computes the expansion of a form. Transforms are only used by the compiler and not by the interpreter. deftransform allows you to add to the optimizations performed by the compiler.

(compiler:deftransform  +  +-of-2  (x y)
 '(system::|+2| ,x ,y))
(compiler:deftransform  +  +-of-many (x &rest y)
 '(system::|+2| ,x (+ ,@y)))
 ;; now an expression like (+ a b c 4 5 7 d e f)
 ;; compiles to use the binary version
 ;; of + (inlined by default),   
 ;; rather than the full (slow) version of +
(compiler:deftransform  list  list-of-1 (x)
 '(cons ,x '()))
(compiler:deftransform  list  list-of-2 (x y)
 '(cons ,x (cons ,y '())))
 ;; save having to call list - 
 ;; cons is inlined by default
(compiler:deftransform  constant  my-trans  (x)
     (cond  ((constantp x)   x)
            ((consp x)     '(quote ,(eval x)))
            (t 'compiler::%pass%)))  ; give up if not a cons
(compile (defun three-list () (constant (list 1 2 3))))
 ;; the function three-list returns the 
 ;; same list (1 2 3)
 ;; every time it is called...

The list-of-2 example returns


as its result, since a similar transform already exists in the compiler, by the name compiler::list*-transform .


deftransform differs from defmacro in various ways:

The evaluation of the body can return compiler:%pass% indicating that the form is not to be expanded (in other words, the transform method has elected to give up trying to improve the code).

The compiler only calls the expander function if the arguments match the lambda list -- macros are unconditionally expanded.

There can be several deftransforms for the same symbol, each having a different name. (The compiler calls each one in turn until one succeeds. This repeats until they all pass, so that the replacement form may itself be transformed.)

If a transform takes keyword arguments the compiler preserves the correct order of evaluation.

A carelessly written deftransform may lead the compiler to transform valid Common Lisp into incorrect code -- there is no semantic checking of the transform.

See also


LispWorks User Guide and Reference Manual - 22 Dec 2009