From: Dave Cooper
Subject: How to find the current method object
Date: 
Message-ID: <3B64E1CB.1C8FA3BB@genworks.com>
Is there a way in standard CL to find the method object which is
currently being run? I want to collect up messages from a given object
and optionally all its superclasses (I know i should be using more
built-in machinery for this, but humor me for now...) I am currently
doing something like this:

(defmethod gdl-rule:%message-list%
  ((self <some-class-name>) &key (depth 0) include-superclasses?) 
 (let ((locals
	(message-list self depth)))
   (append locals (when (and include-superclasses?
                             (next-method-p))
			(call-next-method self
                                          :depth (1+ depth))))))


In the message-list function, I'm doing something like this:

 ....

(let* ((method (nth depth (compute-applicable-methods
                            #'gdl-rule:%message-list% (list self))))
       (type (class-name (first (mop:method-specializers method)))))
 ......

So the really hokey part is that in the message-list function, I am
using depth as an index into the list returned by
compute-applicable-methods. Since self remains the same object for every
next-method invocation, this is the only way I have come up with to find
out which superclass of self is actually being processed in the given
method call.

Any more direct way to suss out what the current method object is (more
specifically, what its specializer classes are)?

Thanks,

 -dave

From: Stanley Knutson
Subject: Re: How to find the current method object
Date: 
Message-ID: <q48nmtoaa6dlfl306vnp0chmgmc4iob7oi@4ax.com>
On Mon, 30 Jul 2001 00:25:47 -0400, Dave Cooper <·······@genworks.com>
wrote:

>
>Is there a way in standard CL to find the method object which is
>currently being run? I want to collect up messages from a given object
>and optionally all its superclasses (I know i should be using more
>built-in machinery for this, but humor me for now...) I am currently
>doing something like this:
>
>(defmethod gdl-rule:%message-list%
>  ((self <some-class-name>) &key (depth 0) include-superclasses?) 
> (let ((locals
>	(message-list self depth)))
>   (append locals (when (and include-superclasses?
>                             (next-method-p))
>			(call-next-method self
>                                          :depth (1+ depth))))))
>
>
>In the message-list function, I'm doing something like this:
>
> ....
>
>(let* ((method (nth depth (compute-applicable-methods
>                            #'gdl-rule:%message-list% (list self))))
>       (type (class-name (first (mop:method-specializers method)))))
> ......
>
>So the really hokey part is that in the message-list function, I am
>using depth as an index into the list returned by
>compute-applicable-methods. Since self remains the same object for every
>next-method invocation, this is the only way I have come up with to find
>out which superclass of self is actually being processed in the given
>method call.
>
>Any more direct way to suss out what the current method object is (more
>specifically, what its specializer classes are)?
>
>Thanks,
>
> -dave

I don't think you need the method object.

Seens to me you really want an :around method on each class

(defmethod local-messages ((self some-class))
   ...)

(defmethod all-messages :around ((self some-class))
   (union (local-message-self)  ;; or append 
         (call-next-method))

The drawback of this is each class then has to specialize _both_ the
local-messages and all-messages list.

If the local messages is dynamic, there is no choice but to do the
above.

If the local-messages content be computable
at compile time [for a language like Java or ICAD defparts]
A better solution [for such a compiler] is like this:

(setf (get 'some-class-being-compiled 'local-messages)
    '(....))

Then the base-object class needs only one method:
(defmethod all-messages ((self base-class))
   (let* ((all-classes (class-precedence-list self))
            (class-local-data
                (mapcar #'(lambda (cl)
                                          (get cl 'local-messages))
                             all-classes))
    (apply #'union class-local-data))

This will have significantly less total code space than specializing
the methods on each class.

- Stanley Knutson
knewt @ alum - nospam .mit.edu
     
From: Stanley Knutson
Subject: Re: How to find the current method object
Date: 
Message-ID: <osromtshga2m3rdlffs0v8hkdo16g1hh6l@4ax.com>
On Sat, 04 Aug 2001 00:23:47 -0700, Stanley Knutson
<·······@nospam.ktiworld.com> wrote:

>On Mon, 30 Jul 2001 00:25:47 -0400, Dave Cooper <·······@genworks.com>
>wrote:
>
>>
>>Is there a way in standard CL to find the method object which is
>>currently being run? I want to collect up messages from a given object
>>and optionally all its superclasses (I know i should be using more
>>built-in machinery for this, but humor me for now...) I am currently
>>doing something like this:
>>
>>(defmethod gdl-rule:%message-list%
>>  ((self <some-class-name>) &key (depth 0) include-superclasses?) 
>> (let ((locals
>>	(message-list self depth)))
>>   (append locals (when (and include-superclasses?
>>                             (next-method-p))
>>			(call-next-method self
>>                                          :depth (1+ depth))))))
>>
>>
>>In the message-list function, I'm doing something like this:
>>
>> ....
>>
>>(let* ((method (nth depth (compute-applicable-methods
>>                            #'gdl-rule:%message-list% (list self))))
>>       (type (class-name (first (mop:method-specializers method)))))
>> ......
>>
>>So the really hokey part is that in the message-list function, I am
>>using depth as an index into the list returned by
>>compute-applicable-methods. Since self remains the same object for every
>>next-method invocation, this is the only way I have come up with to find
>>out which superclass of self is actually being processed in the given
>>method call.
>>
>>Any more direct way to suss out what the current method object is (more
>>specifically, what its specializer classes are)?
>>
>>Thanks,
>>
>> -dave
>
>I don't think you need the method object.
>
>Seens to me you really want an :around method on each class
>
>(defmethod local-messages ((self some-class))
>   ...)
>
>(defmethod all-messages :around ((self some-class))
>   (union (local-message-self)  ;; or append 
>         (call-next-method))
>
>The drawback of this is each class then has to specialize _both_ the
>local-messages and all-messages list.
>
>If the local messages is dynamic, there is no choice but to do the
>above.
>
>If the local-messages content be computable
>at compile time [for a language like Java or ICAD defparts]
>A better solution [for such a compiler] is like this:
>
>(setf (get 'some-class-being-compiled 'local-messages)
>    '(....))

Note: this is effectively storing 'class' data.
Another approach is to either
1) Create a real metaclass [and specify :metaclass in every defclass
being generated by this compiler]
2) Create an 'added class info' object that is stored on the symbol's
plist.  You really don't want the symbol-plist to be more than a few
elements. [this is the approach taken by ICAD]

>
>Then the base-object class needs only one method:
>(defmethod all-messages ((self base-class))
>   (let* ((all-classes (class-precedence-list self))
                                                                    ^
This needs to be (class-precedence-list (class-of self))
[may need mop: package name if on ACL]

>            (class-local-data
>                (mapcar #'(lambda (cl)
>                                          (get cl 'local-messages))
>                             all-classes))
>    (apply #'union class-local-data))
>
>This will have significantly less total code space than specializing
>the methods on each class.
>
>- Stanley Knutson
>knewt @ alum - nospam .mit.edu
>     

Stanley