[pro] Keyword arguments and compiler macros

Nikodemus Siivola nikodemus at random-state.net
Fri Dec 2 08:28:39 UTC 2011


On 1 December 2011 23:12, Juan Jose Garcia-Ripoll

> I _now_ think that the compiler macro processor should simply recognize the
> failure to parse the form and return the original form, unprocessed

I'm not convinced.

Firstly, the (admittedly non-normative) final example in the
DEFINE-COMPILER-MACRO dictionary entry shows that this isn't exactly
traditional or something writers of portable code can expect.

The same example also, as a practical consideration to those trying to
write portable code, shows how using &REST and &ALLOW-OTHER-KEYS makes
writing such compiler macros possible.

However, the possibility of non-constant keywords is not the only
reason it is tricky. Consider this:

  (defun foo (&key a b c) ...)

Let's assume that FOO can be implemented quite efficiently if you know
A comes from BAR. In addition to dealing with constant arguments,
that's one of the major use-cases for compiler-macros after all.

  (define-compiler-macro foo (&whole form &key a b)
     (if (can-optimize-p a b)
         (optimize a b)
         form))

Now let's take a look at a call-site:

  (foo :b (incf i) :a (bar i))

Unless CAN-OPTIMIZE-P recognizes that B may have side-effects and
therefor returns NIL, the compiler-macro has a bug. This means that as
a practical matter compiler-macro writers dealing with keywords
virtually /always/ need to include &REST in their lambda-lists, and
use it to preserve the order of evaluation.

...which in turn means that if even if an implementation makes
compiler-macros fire only when all keywords specified are constant
ones, compiler-macro writers /still/ need to look at &REST.

Relying on the implementation to provide sufficient rebinding to
preserve the order of side-effects would lead to unportable code with
subtle bugs -- the worst kind.

Cheers,

 -- Nikodemus




More information about the pro mailing list