Harnon wrote:Hello again!
Hi.
First of all, packages do not contain macros or functions but symbols and symbols only. Therefore, you don't define macros or functions in packages but in files. See
http://www.flownet.com/ron/packages.pdf for details. Now, on to the main point...
Harnon wrote:I keep getting a strange (too me) error:
Funcall:appendf not a function, but a macro
This indicates that the call to APPENDF has been compiled as a function call. This is to be expected if the macro was not defined at the time the call was compiled, because macros are run at compile-time (macroexpansion time, actually, but let's just ignore the difference for now), which is generally distinct from run-time (unless you're using a pure interpreter, but even then they
may be distinct).
Let's say you COMPILE-FILE a file containing the following:
Code: Select all
(eval-when (:compile-toplevel)
(format t "~%; Compiling DEBUG-STUFF."))
(defmacro debug-stuff (thing)
(format t "~%; Expanding ~A." thing)
(format t "~%; Returning ~A." `(print ,thing))
`(print ,thing))
(eval-when (:compile-toplevel)
(format t "~%; Compiling MULK."))
(defun mulk ()
(debug-stuff (* (debug-stuff (+ 1 2)) 100))
(eval-when (:compile-toplevel)
(format t "~%; Done compiling."))
During COMPILE-FILE, you're going to get the following messages:
Code: Select all
; Compiling DEBUG-STUFF.
; Compiling MULK.
; Expanding (* (DEBUG-STUFF (+ 1 2)) 100).
; Returning (PRINT (* (DEBUG-STUFF (+ 1 2)) 100).
; Expanding (+ 1 2).
; Returning (PRINT (+ 1 2)).
; Done compiling.
This indicates that DEBUG-STUFF has been called twice during the compilation of MULK and its output substituted for the original expressions:
Code: Select all
(defun mulk ()
(print (* (print (+ 1 2)) 100))
The remaining forms are all function calls, so that the definition of MULK that is now dumped into the compiled file might look somewhat like this:
Code: Select all
(defun mulk ()
(funcall 'print (funcall '* (funcall 'print (funcall '+ 1 2)) 100))
Now try LOADing the compiled file and executing MULK:
As you can see, DEBUG-STUFF is not called by MULK because it has already been macroexpanded away by the compiler.
In contrast, what happens when you COMPILE-FILE the following file?
Code: Select all
(eval-when (:compile-toplevel)
(format t "~%; Compiling MULK."))
(defun mulk ()
(debug-stuff (* (debug-stuff (+ 1 2)) 100))
(eval-when (:compile-toplevel)
(format t "~%; Compiling DEBUG-STUFF."))
(defmacro debug-stuff (thing)
(format t "~%; Expanding ~A." thing)
(format t "~%; Returning ~A." `(print ,thing))
`(print ,thing))
(eval-when (:compile-toplevel)
(format t "~%; Done compiling."))
Obviously, at the time MULK is compiled, DEBUG-STUFF is not yet known. So the compiler assumes DEBUG-STUFF to be a function and compiles MULK accordingly:
Code: Select all
(defun mulk ()
(funcall 'debug-stuff (funcall '* (funcall 'debug-stuff (funcall '+ 1 2)) 100))
When you try to call MULK now, the function DEBUG-STUFF is looked for and not found (because there is no such function).