Order of placement in package matters?
Order of placement in package matters?
Hello again!
I keep getting a strange (too me) error:
Funcall:appendf not a function, but a macro
Appendf is a define-modify-macro macro
The point is that this error is fixed by placing the macro before its usage in the package its defined and exported in.
So, if I use it in a function named finden (defined in same package), i have to place the macro definition before in order for everything to work. Otherwise, the error is produced.
What's happening?
I keep getting a strange (too me) error:
Funcall:appendf not a function, but a macro
Appendf is a define-modify-macro macro
The point is that this error is fixed by placing the macro before its usage in the package its defined and exported in.
So, if I use it in a function named finden (defined in same package), i have to place the macro definition before in order for everything to work. Otherwise, the error is produced.
What's happening?
Re: Order of placement in package matters?
Assuming you have copied the appendf code from DEFINE-MODIFY-MACRO's CLHS page, could you post the code for finden? Does finden contain the code that is trying to FUNCALL appendf?
-
- Posts: 94
- Joined: Mon Jul 21, 2008 7:26 am
- Location: München, Germany
- Contact:
Re: Order of placement in package matters?
Hi.Harnon wrote:Hello again!
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...
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).Harnon wrote:I keep getting a strange (too me) error:
Funcall:appendf not a function, but a macro
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."))
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.
Code: Select all
(defun mulk ()
(print (* (print (+ 1 2)) 100))
Code: Select all
(defun mulk ()
(funcall 'print (funcall '* (funcall 'print (funcall '+ 1 2)) 100))
Code: Select all
> (mulk)
3
300
300
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."))
Code: Select all
(defun mulk ()
(funcall 'debug-stuff (funcall '* (funcall 'debug-stuff (funcall '+ 1 2)) 100))
-
- Posts: 447
- Joined: Sat Jun 28, 2008 7:49 am
- Location: Austin, TX
- Contact:
Re: Order of placement in package matters?
Nice explanation, Kompottkin.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Re: Order of placement in package matters?
So basically i have to define all macros before they're used in functions if i want to package them?
Heres code;
Heres code;
Code: Select all
(defun finden (func lst)
(loop for item in lst
for orig = nil then orig
appending (if-let it (funcall func item) (progn (appendf orig (list item))
(list it))
nil) into result
finally (return (values result orig))))
-
- Posts: 94
- Joined: Mon Jul 21, 2008 7:26 am
- Location: München, Germany
- Contact:
Re: Order of placement in package matters?
Thank you!findinglisp wrote:Nice explanation, Kompottkin.
Yep, that's basically what follows from all the above. Macros need to be defined before any forms containing calls to them are compiled.Harnon wrote:So basically i have to define all macros before they're used in functions if i want to package them?
Re: Order of placement in package matters?
Thx guys!
Unfortunately, it appears like i have another package problem. See if you can figure this one out!
Error: When attempting to read the slot's values (slot-value), the slot reader-macro-commune::else is missing from the object #<IT.BESE.ARNESI:IF-FORM # {A9823A1}>.
The strange part is that the consequent and then form present no errors, but the else does.
when i replace (walker else) with (walker (slot-value form arnesi::else)), everything
works fine. Waz happenin?
Unfortunately, it appears like i have another package problem. See if you can figure this one out!
Error: When attempting to read the slot's values (slot-value), the slot reader-macro-commune::else is missing from the object #<IT.BESE.ARNESI:IF-FORM # {A9823A1}>.
The strange part is that the consequent and then form present no errors, but the else does.
when i replace (walker else) with (walker (slot-value form arnesi::else)), everything
works fine. Waz happenin?
Code: Select all
;;error occurs in defgenwalker if-form code
(defpackage :reader-macro-commune (:use :cl :arnesi :utilities))
(in-package :reader-macro-commune
(defgenwalker if-form (consequent then else)
(make-instance 'if-form
:consequent (walker consequent)
:then (walker then)
:else (walker else)))
(defmacro defwalker (generic class (&rest slots) &body body)
`(defmethod ,generic ((form ,class))
(with-slots ,slots form
,@body)))
(defmacro defgenwalker (class (&rest slots) &body body)
`(defwalker walker ,class (,@slots) ,@body))