从 Quicklisp 包中的宏调用函数 [英] Calling function from macro inside Quicklisp package

查看:15
本文介绍了从 Quicklisp 包中的宏调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我把 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆