From: ····@balooga.com
Subject: Macros and CLOS
Date: 
Message-ID: <1114725973.189983.71170@l41g2000cwc.googlegroups.com>
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)))

From: Frode Vatvedt Fjeld
Subject: Re: Macros and CLOS
Date: 
Message-ID: <2hu0lq4jav.fsf@vserver.cs.uit.no>
·····@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
From: Luke Crook
Subject: Re: Macros and CLOS
Date: 
Message-ID: <1114736934.536082.243900@z14g2000cwz.googlegroups.com>
Yes, that makes sense. Thanks.
From: Barry Margolin
Subject: Re: Macros and CLOS
Date: 
Message-ID: <barmar-26ABFF.19400528042005@comcast.dca.giganews.com>
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 ***
From: Luke Crook
Subject: Re: Macros and CLOS
Date: 
Message-ID: <1114737880.792539.260690@o13g2000cwo.googlegroups.com>
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.
From: Kenny Tilton
Subject: Re: Macros and CLOS
Date: 
Message-ID: <6jgce.16798$mp6.2504779@twister.nyc.rr.com>
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
From: Pascal Bourguignon
Subject: Re: Macros and CLOS
Date: 
Message-ID: <8764y6jrf2.fsf@thalassa.informatimago.com>
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.
From: Kalle Olavi Niemitalo
Subject: Re: Macros and CLOS
Date: 
Message-ID: <87d5se15ob.fsf@Astalo.kon.iki.fi>
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.