Calling function from macro inside Quicklisp package

試著忘記壹切 提交于 2019-12-01 04:08:38

问题


I put failing.asd

(in-package :asdf-user)                    

(defsystem "failing"                       
  :description "some code destined to fail"
  :version "0.1"                           
  :author "me"                      
  :components ((:file "package")))         

and package.lisp

(defpackage :failing  
  (:export :foo :bar))

(in-package :failing) 

(defun foo () 42)     

(defmacro bar ()      
  (let ((x (foo)))    
    `(print ,x)))     

(bar)                 

into ~/quicklisp/local-projects/failing. Using Clozure CL with Quicklisp installed, I run

(ql:quickload :failing)

which gives me

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?


回答1:


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).

It has to do with how file compilation works in Common Lisp:

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.

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.

Solutions:

  • 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

  • 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.



来源:https://stackoverflow.com/questions/29442098/calling-function-from-macro-inside-quicklisp-package

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!