Compilation 关于公共Lisp编译顺序的问题
我在一个文件中编写了宏和函数,如下所示:Compilation 关于公共Lisp编译顺序的问题,compilation,macros,lisp,common-lisp,sbcl,Compilation,Macros,Lisp,Common Lisp,Sbcl,我在一个文件中编写了宏和函数,如下所示: (defun测试() (让((x'(1 2 3))) (宏观测试(x real-b) (打印(+1(car real-b()()))) (DEF宏观测试((a b)和车身) `(do(,b,a(cdr,b))) ((不,b)) (@body)) 然后我在repl中加载这个文件并运行(test)。我得到了这个错误: The variable REAL-B is unbound. 但是,当我将defmacro放在defun之前时。一切都很好 我对公共li
(defun测试()
(让((x'(1 2 3)))
(宏观测试(x real-b)
(打印(+1(car real-b()())))
(DEF宏观测试((a b)和车身)
`(do(,b,a(cdr,b)))
((不,b))
(@body))
然后我在repl中加载这个文件并运行(test)
。我得到了这个错误:
The variable REAL-B is unbound.
但是,当我将defmacro
放在defun
之前时。一切都很好
我对公共lisp编译顺序感到困惑。我知道如果defmacro
内部使用了一些函数,那么这些函数应该(eval when(:compile toplevel:load toplevel:execute))
,否则编译将失败
但是,如果宏定义和函数定义在编译时是相同的,那么顺序就很重要,对吗?宏应该位于使用它们的位置之前(如果我使用两个函数,顺序无关紧要)。我可以了解更多关于SBCL编译顺序的详细信息吗?这只适用于SBCL吗?还是按照通用Lisp的标准
谢谢大家! 顺序总是很重要的:当您想要使用宏时,必须知道它。宏执行源转换。如何使用未知宏进行源代码转换
公共Lisp标准不需要多程编译,即首先读取所有源代码并收集所有宏,然后从文件顶部开始编译。CommonLisp中的文件编译只是从头到尾地浏览源代码。以后可能会有多个编译阶段,但这将留给实现
当宏宏测试
未知时,Lisp应该如何编译函数测试
?Lisp编译器需要a)知道它是一个宏,b)需要有它的定义来扩展宏形式
对于通用Lisp,这是一条基本规则:
如果我们有一个表单(foo-bar-baz)
,那么评估基本上是查看foo
如果foo
是特殊运算符->使用该特殊运算符
如果foo
是宏运算符->宏,则展开代码并重新启动
如果foo
是一个函数->则使用求值参数调用该函数
否则会出错
在编译中看起来类似:
如果foo
是一个特殊的操作符->编译这个特殊的表单
如果foo
是宏运算符->宏,则展开宏窗体并编译该代码
如果foo
是一个函数->编译该函数表单
else->warn,然后假设foo
是一个函数,并编译对该名称的未来函数的调用
我认为文件编译是允许的(但我认为不是必需的?)将有关未知函数的警告推迟到文件的末尾,以便像(defun foo(…)(bar…)这样的事情。。。(defun bar(…)…(foo…)
可以在没有噪声的情况下编译。当然,如果一个编译器没有做到这一点,那么使用起来会很烦人@tfb:是的,编译单元中的警告已经存在,但是如果仍然有必要的话,它将在有用的时间传达给用户。在文件编译单元中,编译器可能也不会直接编译未知函数调用以使用后期绑定,但可能会等待稍后的定义…因此,假设foo是函数是函数的一个原因,如果我理解正确,函数顺序看起来无关紧要,但宏会起作用。回到(eval when(:compile toplevel))
,这意味着内部的表单在编译时会比所有其他表单先编译,对吗?@ccQpein:no,(eval when(:compile toplevel)…)
意味着文件编译器在顶级查看时会对附带的表单进行评估。