I was wondering what namespace does macros use in Common Lisp? It seems
that it can't be the variable namespace because obviously a macro is
not a variable, but then it can't be the function namespace either
because a macro has no runtime presence. Can anyone briefly explain
exactly how the macro system works? I looked at the full expansions of
some macros, and it seems that it uses the EVAL-WHEN special form to
eval at compile time. But the generated lisp is like nothing I've ever
seen and I have no idea what most of it is doing.
for (defmacro f (list) (quote list))
it generated this:
(PROGN (EVAL-WHEN (:COMPILE-TOPLEVEL)
(EXCL::CHECK-LOCK-DEFINITIONS-COMPILE-TIME 'F 'FUNCTION
'DEFMACRO (FBOUNDP 'F)))
(LET* ((#:G105
#'(LAMBDA (EXCL::**MACROARG** EXCL::..ENVIRONMENT..)
(DECLARE (IGNORE-IF-UNUSED EXCL::..ENVIRONMENT..))
(EXCL::DT-MACRO-ARGUMENT-CHECK 1 1
EXCL::**MACROARG** :MACRO)
(BLOCK F
(LET* ()
(LET* ((#:G103 (CDR EXCL::**MACROARG**))
(LIST (EXCL::CAR-FUSSY #:G103 'LIST))
(#:G104
(EXCL::LAMBDASCAN-MAXARGS
0
(CDR #:G103)
'(LIST))))
(DECLARE (IGNORABLE #:G104))
'LIST))))))
(EXCL::.INV-MACRO-FUNCTION 'F NIL #:G105))
(EXCL::SET-FUNC_NAME (MACRO-FUNCTION 'F) 'F)
(EXCL::.INV-FUNC_FORMALS (FBOUNDP 'F) '(LIST))
(EVAL-WHEN (:COMPILE-TOPLEVEL)
(SYSTEM:AUGMENT-ENVIRONMENT
SYSTEM:*COMPILATION-UNIT-ENVIRONMENT*
:REUSE T
:MACRO 'F
:LOCATIVE (LIST #'(LAMBDA (EXCL::**MACROARG**
EXCL::..ENVIRONMENT..)
(DECLARE
(IGNORE-IF-UNUSED
EXCL::..ENVIRONMENT..))
(EXCL::DT-MACRO-ARGUMENT-CHECK
1
1
EXCL::**MACROARG**
:MACRO)
(BLOCK
F
(LET*
()
(LET*
((#:G103 (CDR EXCL::**MACROARG**))
(LIST
(EXCL::CAR-FUSSY #:G103 'LIST))
(#:G104
(EXCL::LAMBDASCAN-MAXARGS
0
(CDR #:G103)
'(LIST))))
(DECLARE (IGNORABLE #:G104))
'LIST)))))))
(REMPROP 'F 'EXCL::%FUN-DOCUMENTATION) (RECORD-SOURCE-FILE 'F)
'F)
-Jeffery
Jeffery Zhang wrote:
> I was wondering what namespace does macros use in Common Lisp? It seems
> that it can't be the variable namespace because obviously a macro is not
> a variable, but then it can't be the function namespace either because a
> macro has no runtime presence. Can anyone briefly explain exactly how
> the macro system works? I looked at the full expansions of some macros,
> and it seems that it uses the EVAL-WHEN special form to eval at compile
> time. But the generated lisp is like nothing I've ever seen and I have
> no idea what most of it is doing.
It's not correct that a macro doesn't have a runtime representation.
First of all, it depends on whether an interpreter or a compiler is used
to run your program. If a compiler is used, it is guaranteed that all
macros are fully expanded at runtime, but if an intepreter is used it
may happen that your macros are repeatedly expanded on each invocation,
so they have to have a runtime representation in that case. Even if your
macros are fully expanded and your code doesn't include any macro
invocations anymore, you may still be able to refer to them in calls to
EVAL or MACRO-FUNCTION.
Further note that macros cannot only be invoked in place of functions,
but there are also symbol macros that can be used in place of variables.
It is indeed the case that "regular" macros are associated with the
function namespace and symbol macros are associated with the variable
namespace. There is evidence for this in the ANSI CL spec - see FBOUNDP
and SYMBOL-FUNCTION, for example, which are specified to be valid for
macros. It's just not specified what kind of value you get when you call
SYMBOL-FUNCTION for a macro.
It indeed makes sense that macros are in the function namespace and
symbol macros in the variable namespace, because whenever a macro is
lexically visible, a function of that same name cannot be lexically
visible, and vice versa. Same for symbol macros and variables. Consider
the following code.
(flet ((foo (...) ...))
(macrolet ((foo (...) ...))
...
(foo ...)
...))
It's clear that the invocation of FOO here refers to the local macro
definition, not the outer function definition. If macros and functions
were in different namespaces, this kind of shadowing would be cumbersome
to implement. Again, same for symbol macros and variables, as you can
see in the following code.
(let ((x ...))
(symbol-macrolet ((x ...))
... x ...))
I hope this helps.
Pascal
--
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/