从 Quicklisp 包中的宏调用函数 [英] Calling function from macro inside Quicklisp package
问题描述
我把 failing.asd
(in-package :asdf-user)
(defsystem "failing"
:description "some code destined to fail"
:version "0.1"
:author "me"
:components ((:file "package")))
和package.lisp
(defpackage :failing
(:export :foo :bar))
(in-package :failing)
(defun foo () 42)
(defmacro bar ()
(let ((x (foo)))
`(print ,x)))
(bar)
进入 ~/quicklisp/local-projects/failing.使用安装了 Quicklisp 的 Clozure CL,我运行
into ~/quicklisp/local-projects/failing. Using Clozure CL with Quicklisp installed, I run
(ql:quickload :failing)
这给了我
To load "failing":
Load 1 ASDF system:
failing
; Loading "failing"
[package failing]
> Error: Undefined function FOO called with arguments () .
> While executing: BAR, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Retry applying FOO to NIL.
> Type :? for other options.
似乎我无法从包内的宏中调用函数.为什么不呢?
It seems I can't call a function from a macro inside the package. Why not?
推荐答案
只有当文件在加载之前被编译时才会发生这种情况.通常它与 ASDF(这是一种管理文件依赖关系和编译/加载代码的工具)或包(它们是命名空间,与 ASDF 没有任何关系)无关.
That can only happen when the file gets compiled before loaded. Generally it has nothing to do with ASDF (which is a tool to manage file dependencies and to compile/load code) or packages (which are namespaces and are not in any way related to ASDF).
这与 Common Lisp 中文件编译的工作方式有关:
文件编译器看到函数foo
并编译它->它的代码被写入文件.它不会(!)将代码加载到编译时环境中.
The file compiler sees the function foo
and compiles it -> the code for it gets written to a file. It does not (!) load the code into the compile-time environment.
文件编译器然后看到宏栏并编译它 -> 代码被写入文件.它确实 (!) 将代码加载到编译时环境中.
The file compiler then sees the macro bar and compiles it -> the code gets written to a file. It does (!) load the code into the compile-time environment.
文件编译器然后看到宏形式(bar)
并想要扩展它.它调用宏函数bar
.它调用了未定义的 foo
,因为它不在编译时环境中.
The file compiler then sees the macro form (bar)
and wants to expand it. It calls the macro function bar
. Which calls foo
, which is undefined, since it is not in the compile-time environment.
解决方案:
将函数定义放在ASDF系统的单独文件中,提前编译/加载.
put the function definition in a separate file in the ASDF system and compile/load it earlier.
将函数作为局部函数放入宏中
put the function inside the macro as a local function
在函数定义周围放置 (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE) ...)
.它导致定义在编译时执行.
put (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE) ...)
around the function definition. It causes the definition to be executed at compile-time.
记住:文件编译器需要知道宏函数 -> 否则它将无法对代码进行宏扩展.普通函数只是在编译文件期间被编译,而不是在编译时加载.
Remember: the file compiler needs to know macro functions -> otherwise it would not be able to macroexpand code. Ordinary functions just get compiled, but not loaded at compile time, during compilation of a file.
这篇关于从 Quicklisp 包中的宏调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!