And I don't think the function/value split is even the most important namespacing it does with regards to macro hygiene ("functions are less likely to be shadowed" always struck me as a kind of weak argument). Symbols being namespaced under packages is a much more robust solution:
CL-USER> (defmacro m (x) `(car ,x))
M
CL-USER> (defpackage :p)
#<PACKAGE "P">
CL-USER> (in-package :p)
#<COMMON-LISP:PACKAGE "P">
P> (cl:macroexpand '(cl-user::m x))
(COMMON-LISP:CAR X)
CL:CAR isn't accessible in P, so (car x) by itself would signal
UNDEFINED-FUNCTION, but the macro works correctly. Defining a P::CAR function
wouldn't change anything.That isn't just for functions, either, eg if you do:
(defmacro awhen (pred &body body)
`(let ((it ,pred))
(when it ,@body)))
(where you want to leak IT), and then import AWHEN but not IT, you'll get an
error that YOUR-PACKAGE::IT isn't bound to anything when you try to use it; it
doesn't matter that AWHEN-PACKAGE:IT is bound.I don't disagree with anything you said, I just think it made CL macros look flimsier than they are.