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