From: Jon Bills
Subject: Finding which classes implement a slot
Date: 
Message-ID: <b15rgh$eef2@cvis05.marconicomms.com>
Given a slot name, is there a means of finding which classes derived from a
common root implement that slot? Suppose I have this hierarchy:

(defclass message ()
  ())

(defclass 014d (message)
  ((baud-rate)))

(defclass 016b (message)
  ((subrack-id)
   (cardslot-id)
   (channel-to-monitor)))

(defclass 0304 (message)
  ((subrack-id)
   (cardslot-id)))

If I wanted to find out which derivatives of message contain a slot named
"subrack-id", what would be the best way of going about it?

Thanks,

Jon.

From: Nils Goesche
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <lyn0lliftt.fsf@cartan.de>
"Jon Bills" <·········@hotmail.com> writes:

> Given a slot name, is there a means of finding which classes derived
> from a common root implement that slot? Suppose I have this
> hierarchy:
> 
> (defclass message ()
>   ())
> 
> (defclass 014d (message)
>   ((baud-rate)))
> 
> (defclass 016b (message)
>   ((subrack-id)
>    (cardslot-id)
>    (channel-to-monitor)))
> 
> (defclass 0304 (message)

A class name should be a non-nil symbol, not a number.

>   ((subrack-id)
>    (cardslot-id)))
> 
> If I wanted to find out which derivatives of message contain a slot
> named "subrack-id", what would be the best way of going about it?

That's what the MetaObject Protocol (MOP) is for.  In LispWorks, its
functions are exported from the HCL package.  Then you can do
something like

(defpackage "SLOTS"
  (:use "CL")
  (:export "FIND-SLOTS"))

(in-package "SLOTS")

(defclass message ()
  ())

(defclass class-014d (message)
  ((baud-rate)))

(defclass class-016b (message)
  ((subrack-id)
   (cardslot-id)
   (channel-to-monitor)))

(defclass class-0304 (message)
  ((subrack-id)
   (cardslot-id)))

(defun find-slots (name base)
  (let (classes)
    (labels ((process-class (base)
               (when (find name (hcl:class-slots base)
                           :key #'hcl:slot-definition-name :test #'eq)
                 (push (class-name base) classes))
               (mapc #'process-class (hcl:class-direct-subclasses base))))
      (process-class (find-class base))
      classes)))

and then:

SLOTS 26 > (find-slots 'subrack-id 'message)
(CLASS-016B CLASS-0304)

To find the MOP functions in other implementations (if present), look
for them with APROPOS.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Jon Bills
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <b1628e$e1c5@cvis05.marconicomms.com>
Nils Goesche wrote:
> "Jon Bills" <·········@hotmail.com> writes:
>
> A class name should be a non-nil symbol, not a number.

OK, thanks for pointing that out.

>> If I wanted to find out which derivatives of message contain a slot
>> named "subrack-id", what would be the best way of going about it?
>
> That's what the MetaObject Protocol (MOP) is for.

I suspected so, but I haven't had much to do with MOP so far. AMOP is next
on my "to buy" list.

>  In LispWorks, its
> functions are exported from the HCL package.  Then you can do
> something like

[...]

Thanks Nils, that's exactly what I was looking for.

Jon.
From: Matthew Danish
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <20030128104639.L27240@lain.cheme.cmu.edu>
On Tue, Jan 28, 2003 at 01:56:32PM -0000, Jon Bills wrote:
> Nils Goesche wrote:
> > "Jon Bills" <·········@hotmail.com> writes:
> >
> > A class name should be a non-nil symbol, not a number.
> 
> OK, thanks for pointing that out.

This, BTW, doesn't stop you from using |123|, which is the symbol with
the name "123".

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Nils Goesche
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <lyisw9ifcl.fsf@cartan.de>
I <······@cartan.de> wrote:

> (defun find-slots (name base)
>   (let (classes)
>     (labels ((process-class (base)
>                (when (find name (hcl:class-slots base)
>                            :key #'hcl:slot-definition-name :test #'eq)
>                  (push (class-name base) classes))
>                (mapc #'process-class (hcl:class-direct-subclasses base))))
>       (process-class (find-class base))
>       classes)))

I should mention that this might return classes several times (but
should terminate in any case).  If this bothers you, make that

(defun find-slots (name base)
  (let (classes)
    (labels ((process-class (base)
               (when (find name (hcl:class-slots base)
                           :key #'hcl:slot-definition-name :test #'eq)
                 (push (class-name base) classes))
               (mapc #'process-class (hcl:class-direct-subclasses base))))
      (process-class (find-class base))
      (delete-duplicates classes :test #'eq)))

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Steven M. Haflich
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <3E376FC1.2030803@alum.mit.edu>
Nils Goesche wrote:
> (defun find-slots (name base)
>   (let (classes)
>     (labels ((process-class (base)
>                (when (find name (hcl:class-slots base)
>                            :key #'hcl:slot-definition-name :test #'eq)
>                  (push (class-name base) classes))
>                (mapc #'process-class (hcl:class-direct-subclasses base))))
>       (process-class (find-class base))
>       classes)))

There are a couple problems with this solution, although the general 
notion is correct and pedagogiclly useful.

First, class-slots is _required_ to signal error if the class is not
yet finalized.  Perhaps LispWorks is eager about finalization, but 
still, it is possible to define a class that cannot be finalized, so I 
can't imagine how this code could work if it encountered such a 
"abstract" mixin.  It would be safer to use class-direct-slots instead.

Even if modified to handle unfinalized classes, the code will still blow 
up if it encounters a forward-reference-class (i.e. a not-yet-defined 
subclass) because neither class-direct-slots nor class-direct-subclasses 
is defined for a forward-reference-class.  A fix would be to wrap a test 
around the body of process-class.

Finally, this function doesn't return _classes_ that directly define a 
particular slot.  Rather it returns the _names_ of these classes. 
Generally in MOP programming, one immediately resolves class names to 
class objects, and rarely ever perform the inverse operation.  The MOP 
nearly everywhere operates on classes, not class names, and MOP-using 
programs should do the same.  Classes are first class objects with 
object identity, and there are any number of circumstances where classes 
might have no meaningful name, or where multiple class objects could 
have the same name.
From: Gerd Moellmann
Subject: Re: Finding which classes implement a slot
Date: 
Message-ID: <86n0lkuse2.fsf@gerd.free-bsd.org>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> neither class-direct-slots nor class-direct-subclasses is defined
> for a forward-reference-class.

FWIW, AMOP defines both for forward-referenced classes.