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