I am trying to generate a defmethod from a macro but am receiving a "no
method is applicable" error, even from a macroexpand.
Any insights?
-Luke
(defclass an-object ()
((id :accessor id :initarg :id)))
(setf obj (make-instance 'an-object :id 100))
(defmacro defscript (object &rest rest)
`(defmethod update ((obj an-object) (obj-id (eql ,(id object)))
(id object))))
(pprint (macroexpand-1 '(defscript obj)))
·····@balooga.com" <····@balooga.com> writes:
> (setf obj (make-instance 'an-object :id 100))
>
> (defmacro defscript (object &rest rest)
> `(defmethod update ((obj an-object) (obj-id (eql ,(id object)))
> (id object))))
>
> (pprint (macroexpand-1 '(defscript obj)))
What gets evaluated at expansion-time is (id object), where object in
this case is bound to the symbol obj, for which there is no id
method. You probably want to apply id to the symbol-value of obj, so
try
(defmacro defscript (name &rest rest)
`(defmethod update ((obj an-object) (obj-id (eql ,(id (symbol-value name))))
,(id (symbol-value name))))
--
Frode Vatvedt Fjeld
In article <··············@vserver.cs.uit.no>,
Frode Vatvedt Fjeld <······@cs.uit.no> wrote:
> ·····@balooga.com" <····@balooga.com> writes:
>
> > (setf obj (make-instance 'an-object :id 100))
> >
> > (defmacro defscript (object &rest rest)
> > `(defmethod update ((obj an-object) (obj-id (eql ,(id object)))
> > (id object))))
> >
> > (pprint (macroexpand-1 '(defscript obj)))
>
> What gets evaluated at expansion-time is (id object), where object in
> this case is bound to the symbol obj, for which there is no id
> method. You probably want to apply id to the symbol-value of obj, so
> try
>
> (defmacro defscript (name &rest rest)
> `(defmethod update ((obj an-object) (obj-id (eql ,(id (symbol-value
> name))))
> ,(id (symbol-value name))))
This macro design seems misguided. Remember, macros normally run at
compile time, so will OBJ have the correct value then? At a minimum,
the SETF needs to be in an EVAL-WHEN to ensure it gets executed when you
use COMPILE-FILE.
Also, make sure that your class has a MAKE-LOAD-FORM method so that the
object can be dumped into the fasl file. And then you may need to take
special measures to ensure that objects that were EQL at compile time
will be EQL when you load all the files.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
Yikes! I'll explain my intent and perhaps someone can suggest a better
solution.
I currently have an "Engine" that calls an "update" method on a Sprite
object. This update method then FUNCALL's a function that I set
dynamically depending on the action I want the sprite to perform (for
example, a bounce or a ping-pong effect). This is equivalent to my Java
code.
I thought I could do this in a more Lispy way by using CLOS and
creating methods to perform an action. These methods would be
specialized on a specific Sprite object (hence the checking for the
sprite ID). The defscript macro creates these specialized update
methods. Modyfiying the Sprite behaviour at runtime would them simply
be a matter of evaluating defscript with the sprite and a different
sequence of commands.
I'm open to suggestions.
Luke Crook wrote:
> Yikes! I'll explain my intent and perhaps someone can suggest a better
> solution.
>
> I currently have an "Engine" that calls an "update" method on a Sprite
> object. This update method then FUNCALL's a function that I set
> dynamically depending on the action I want the sprite to perform (for
> example, a bounce or a ping-pong effect). This is equivalent to my Java
> code.
>
> I thought I could do this in a more Lispy way by using CLOS and
> creating methods to perform an action. These methods would be
> specialized on a specific Sprite object (hence the checking for the
> sprite ID). The defscript macro creates these specialized update
> methods. Modyfiying the Sprite behaviour at runtime would them simply
> be a matter of evaluating defscript with the sprite and a different
> sequence of commands.
>
> I'm open to suggestions.
>
http://common-lisp.net/project/cells/
My RoboCup soccer players changed their behavior automagically as the
game went on, and different players could have different ways of
reacting to the same situation, even though they were instances of the
same class.
There is no need, btw, for explicit calls to any update methods. The
behavior-deciding rules simply accessed visual, aural, and body-sense
info. When those changed, the behavior got redecided because the /Cells/
engine saw to it that the sensory change propagated to a behavioral change.
Various tricks let you avoid excessive computation.
kenny
--
Cells? Cello? Cells-Gtk?: http://www.common-lisp.net/project/cells/
Why Lisp? http://lisp.tech.coop/RtL%20Highlight%20Film
"Doctor, I wrestled with reality for forty years, and I am happy to
state that I finally won out over it." -- Elwood P. Dowd
Frode Vatvedt Fjeld <······@cs.uit.no> writes:
> ·····@balooga.com" <····@balooga.com> writes:
>
>> (setf obj (make-instance 'an-object :id 100))
>>
>> (defmacro defscript (object &rest rest)
>> `(defmethod update ((obj an-object) (obj-id (eql ,(id object)))
>> (id object))))
>>
>> (pprint (macroexpand-1 '(defscript obj)))
>
> What gets evaluated at expansion-time is (id object), where object in
> this case is bound to the symbol obj, for which there is no id
> method. You probably want to apply id to the symbol-value of obj, so
> try
>
> (defmacro defscript (name &rest rest)
> `(defmethod update ((obj an-object) (obj-id (eql ,(id (symbol-value name))))
> ,(id (symbol-value name))))
Which shows that you don't want a macro here but a function:
(defun defscript (object &rest rest)
(eval `(defmethod update ((obj an-object) (obj-id (eql ,(id object)))
(id object))
;; updating
)))
(let ((obj (make-instance 'an-object :id 100)))
(defscript obj)
(update obj (id obj) (make-instance 'object)))
--
__Pascal Bourguignon__ http://www.informatimago.com/
Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.
Frode Vatvedt Fjeld <······@cs.uit.no> writes:
> What gets evaluated at expansion-time is (id object), where object in
> this case is bound to the symbol obj, for which there is no id
> method.
Is there any reason to call ID at macroexpand time?
Remember that eql specializer forms are evaluated at run time:
(defmacro defscript (object &rest rest)
`(defmethod update ((obj an-object) (obj-id (eql (id ,object)))
(id object))))
I don't know what UPDATE's third parameter ID is for, so I left
it unchanged.