Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!zaphod.mps.ohio-state.edu!magnus.ircc.ohio-state.edu!tut.cis.ohio-state.edu!GILGAMESH.CS.UMASS.EDU!Gallagher From: Gallagher@GILGAMESH.CS.UMASS.EDU (Kevin Gallagher) Newsgroups: comp.lang.clos Subject: Re: accessing clos objects Message-ID: <2875458505-365193@Gilgamesh> Date: 13 Feb 91 18:28:25 GMT Sender: welch@tut.cis.ohio-state.edu Distribution: inet Organization: CommonLoops Lines: 112 > Date: Tue, 12 Feb 91 14:48:41 PST > From: Jon L White > > Here is an an example of the more vanilla approach, putting the > enumeration listing in *two* places: > > (defclass enumeration-mixin () > ((instances :initform nil :allocation :class :accessor class-instances))) Note that in this example the INSTANCES slot will be shared by all subclasses of ENUMERATION-MIXIN, and so will contain all instances of all subclasses. In the context of this discussion this is probably not what is desired. More likely, you would like (CLASS-INSTANCES ) to return a list of all instances of class X and only instances of class X. For example, the following defines two classes EC-1 and EC-2 which use ENUMERATION-MIXIN from JonL's message. (defclass ec-1 (enumeration-mixin) ((z-axis :initform nil :accessor z-axis))) (defclass ec-2 (enumeration-mixin) ((x-axis :initform nil :accessor x-axis))) (make-instance 'ec-1) (setq x1 (make-instance 'ec-1)) (setq x2 (make-instance 'ec-2)) ;; This is probably not what you want, because it has instances ;; of EC-1 and EC-2 > (class-instances x1) (# # #) > (class-instances x2) (# # #) ;; Aside: The table is more like what you want ;; (an alist of ( . )). > *enumerations-map* ((# #) (# # #)) Using the simple mixin approach, the only way to get around this is to add a slot spec for INSTANCES in each subclass. e.g., (defclass enumerated-class-1 (enumeration-mixin) ((instances :allocation :class) (z-axis :initform nil :accessor z-axis))) This is obviously undesirable. The metaclass solution presented also has the same problem, because the `maximal' class (ENUMERATED-OBJECT) has a class allocated slot (INSTANCES) which is used to hold all the instances. One way to fix this would be to have an instance allocated slot in the metaclass itself rather than in the maximal class (i.e., ENUMERATED-CLASS rather than ENUMERATED-OBJECT). For example, ;; First, start this guy out as a plain old 'standard-class' class. ;; This class now has no slots, but is still used to specialize methods. (defclass enumerated-object () ()) (defclass enumerated-class (standard-class) ((clos::direct-superclasses :initform (list (find-class 'enumerated-object))) (instances :initform nil :accessor class-instances-internal))) (defmethod clos-system:validate-superclass ((class enumerated-class) (super standard-class)) t) (change-class (find-class 'enumerated-object) (find-class 'enumerated-class)) (defmethod class-instances ((obj enumerated-object)) (class-instances-internal (class-of obj))) (defmethod (setf class-instances) (nv (obj enumerated-object)) (setf (class-instances-internal (class-of obj)) nv)) (defmethod initialize-instance :after ((x enumerated-object) &rest w) (declare (ignore w)) (push x (class-instances x))) (defclass ec-1 () ((z :initform nil :documentation "Zome Zlot")) (:metaclass enumerated-class)) (defclass ec-2 () ((x :initform nil :documentation "Xome Xlot")) (:metaclass enumerated-class)) > (make-instance 'ec-1) # > (setq x1 (make-instance 'ec-1)) # > (setq x2 (make-instance 'ec-2)) # > (class-instances x1) (# #) > (class-instances x2) (#)