我在一个文件中这样写了一个宏和一个函数:
(defun test ()
(let ((x '(1 2 3)))
(macro-test (x real-b)
(print (+ 1 (car real-b))))))
(defmacro macro-test ((a b) &body body)
`(do ((,b ,a (cdr ,b)))
((not ,b))
,@body))
然后我在repl中加载此文件并运行(test)
。我收到此错误:
The variable REAL-B is unbound.
但是,当我放defmacro
之前 defun
时。一切都很好。
我对通用的Lisp编译顺序感到困惑。我知道defmacro
内部是否使用了某些功能,这些功能应为(eval-when (:compile-toplevel :load-toplevel :execute))
,否则编译将失败。
但是,如果宏定义和函数定义在编译时相同,则顺序很重要,对吗?宏应该位于使用它们的位置(如果我做两个函数,顺序无关紧要)。我可以详细了解SBCL的编译顺序吗?而且仅适用于SBCL吗?还是使用Common Lisp的标准?
谢谢!
顺序总是很重要:当您要使用宏时,必须知道它。
当宏test
未知时,Lisp应该如何编译函数macro-test
? Lisp编译器需要a)知道它是一个宏,并且b)需要有其定义才能扩展宏形式。
对于Common Lisp,这是一个基本规则:
[如果我们有(foo bar baz)
形式,则评估基本上看foo
。
foo
是特殊运算符->使用该特殊运算符foo
是宏运算符->宏展开代码,然后重新开始foo
是一个函数->使用已评估的参数调用该函数在编译中看起来很相似:
foo
是特殊运算符->编译该特殊运算符foo
是宏运算符->宏,展开代码并编译该代码foo
是一个函数->编译该函数调用foo
是一个函数,并编译对该名称的将来函数的调用