From: Frederick C. Gibson, Architect
Subject: Querying Class object to get instances
Date: 
Message-ID: <7juf22$2ug@dfw-ixnews11.ix.netcom.com>
Is there a way in CLOS to get a list of all instances from the class object
of which the instances are members?

Thanks!

Fred Gibson, Architect

·········@gibson-design.com     Architecture Designed Objectively
==================================-----------||||||||||||||||||||||
Frederick Clifford Gibson Architect & Associates

     1220 14th Avenue Suite 106
     San Francisco, CA  94122
     415.753.3797 |tel|  415.759.8848 |fax|

     (c)1999 http://www.gibson-design.com

     EASG: Epistemology-Aesthetics Study Group
           http://www.gibson-design.com/philosophy
     ART:  American Renaissance for the Twenty-First Century
           http://www.art-21.org

From: Kent M Pitman
Subject: Re: Querying Class object to get instances
Date: 
Message-ID: <sfw909pdmwn.fsf@world.std.com>
"Frederick C. Gibson, Architect" <·········@gibson-design.com> writes:

> Is there a way in CLOS to get a list of all instances from the class object
> of which the instances are members?

Not by default.  You can, in an implementation that supports a MOP,
use a user-defined metaclass that upon instantiation logs the instances.

You can also, on a special-case basis for a specific class, do this
without metaclasses by just adding an after method on INITIALIZE-INSTANCE
for the class that pushes the element onto some list.

 (defvar *the-foos* '())

 (defmethod initialize-instance :after ((self foo) &key)
   (push self *the-foos*))

There is a problem with doing it that way (which is why metclasses are
a better way) because if you subclass FOO you won't get a new
variable.  You might think you could solve this by doing:

 (defclass foo ()
   ((all-instances :allocation :class :accessor all-instances :initform '())))

and then pushing onto (all-instances self), which would be the class
slot. But the problem is that you'll get the same bug because when you
subclass a class with a slot that uses :allocation :class, you do not
get a new slot for each subclass--the subclasses all share the same
slot.  [The Dylan lanuage has something that would in CL be called
:allocation :each-subclass, which is what you really want and CL does
not provide.]

SOMETIMES having the shared variable is actually right, but often it is not
so you have to think about it in advance.

I have sometimes worked around this by doing

 (defvar *all-instances* nil)

 (defmethod initialize-instance :after ((self instance-recording-class) &key)
   (push self (getf *all-instances* (class-of self))))

 (defmethod all-instances ((self instance-recording-class))
   (getf *all-instances* (class-of self)))

or something like that.  I think if you search in Deja News, or maybe
even look in the FAQ, you can probably find one or more worked examples
of doing something like this with the MOP stuff, that I'm not super-familiar
with mostly because I've always preferred to write really portable code
that doesn't require the MOP.

Incidentally, whether you use the MOP or not, there is an issue that you
can end up really defeating garbage collection if you keep track of all
the instances, so be very careful with anything like this and use it only
if you really have to.  I think some implementations may have tools that
sweep the address space looking for instances exactly to avoid the gc locking
problem, but that's not a basic CL operation, and implementations are not
required to include enough information in the image to actually be able to
recover such...  (Such tools would necessarily cons, though, upon 
demand, and so you'd risk holding a pointer to things that want to GC even
if you use one of them. )

You could also use weak hash tables (which most implementations provide
but are not standard) to help avoid the gc locking problem for instances.
From: Erik Naggum
Subject: Re: Querying Class object to get instances
Date: 
Message-ID: <3138893113792349@naggum.no>
* "Frederick C. Gibson, Architect" <·········@gibson-design.com>
| Is there a way in CLOS to get a list of all instances from the class object
| of which the instances are members?

  no, but some Common Lisp implementations provide access to heap walkers
  from their memory management subsystems that return a list of all "live"
  objects of a particular system type.  STANDARD-INSTANCE is typically such
  a system type, but you can easily test for the correct classness
  yourself.  which Common Lisp are you using?

#:Erik
-- 
@1999-07-22T00:37:33Z -- pi billion seconds since the turn of the century