Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!bcm!dimacs.rutgers.edu!seismo!uunet!tut.cis.ohio-state.edu!LUCID.COM!jonl From: jonl@LUCID.COM (Jon L White) Newsgroups: comp.lang.clos Subject: accessing clos objects Message-ID: <9102122248.AA22313@kolyma> Date: 12 Feb 91 22:48:41 GMT References: <9102121807.AA16036@cheops.cis.ohio-state.edu> Sender: welch@tut.cis.ohio-state.edu Distribution: inet Organization: CommonLoops Lines: 129 I would think that whether you "record" the instances in a global list or in a shared slot is independent of whether you use the :metaclass/MAKE-INSTANCE approach, or the more plain mixin-class/INITIALIZE-INSTANCE approach. For example, the the :metaclass approach could provide the "class" slot simply by having a "maximal"class in that particular metaclass (just as STANDARD-OBJECT is the "maximal" class in STANDARD-CLASS) and this class has the direct "class" slot; but the vanilla mixin-class approach would just have the inherited mixin provide the class slot. On the other hand, with many implementations, there may be a performance penalty to pay if you use the approach that overrides the MAKE-INSTANCE method on STANDARD-CLASS. In your example, you have a method on INSTANCE-RECORDING-CLASS that "overrides" the one on STANDARD-CLASS. [Note: recent metaboject proposals define "extends" and "overrides" in more technical terms, and in that terminology, "extends" is the corect word; but without requiring every reader of this list to read these documents, I think "overrides" is more intuitively clear. As the distinction between "extends" and "overrides" becomes generally known, I believe it will be a better set of terms; but for right now . . . ] I will now provide examples of doing it both ways; partly to show how simple the "vanilla" approach is, and partly to show how to create metaclasses with "maximal" elements (at least in Lucid's 4.0 release). The first approach is pure, standard CLOS; the second, of course, touches on the not-yet-standard metaobject protocols, and parts will no doubt change as time goes by. 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))) # > (setq *enumerations-map* nil) NIL > (defmethod initialize-instance :after ((x enumeration-mixin) &rest w) (declare (ignore w)) (let* ((direct-class (class-of x)) (entry (or (assq direct-class *enumerations-map*) (car (push (cons direct-class nil) *enumerations-map*))))) (push x (cdr entry)) ;in global place (push x (class-instances x)) ;in shared slot )) # > (defclass enumerated-class-1 (enumeration-mixin ;could have many more ; superclasses here. ) ((z-axis :initform nil :accessor z :documentation "What the Z?"))) # > (make-instance 'enumerated-class-1) # > (setq x (make-instance 'enumerated-class-1)) # > *enumerations-map* ((# # #)) > (class-instances x) (# #) > Now, here's an example of the metaclass approach. Note the use of CLOS-SYSTEM:VALIDATE-SUPERCLASS instead of PCL's CHECK-SUPERCLASS-COMPATIBILITY. Likely the VALIDATE-SUPERCLASS terminology will become a standard. However, I'm not sure whether or not a technique for the creation of a "maximal" element of a metaclass is part of the emerging proposals. In the code below, this his how you would do it in the patched Lucid 4.0 release; in particular, note the circular dependencies between this "maximal" element and the metaclass, and how the use of CHANGE-CLASS fixes up the problem. In the current Symbolics release, it might be that a maximal element is supported by some additional metaobject generic function; but in Lucid's release, it is determined by the default value form for the class slot CLOS::DIRECT-SUPERCLASSES [note well, this is an instance slot in class objects, and not a shared slot; it is accessed by the function from the "de-facto" standards proposal CLOS:CLASS-DIRECT-SUPERCLASSES.] In the code below, all use of CLOS::... symbols is Lucid-speicifc; and all uses of CLOS-SYSTEM:... symbols is Lucid specific *except* for the one CLOS-SYSTEM:VALIDATE-SUPERCLASS -- I believe this one will be in the standards proposals, although at the time of Lucid's release, it was still being debated. All uses of CLOS:... symbols are from the set of three or four dozen functions that Symbolics and Lucid (and possibly others?) subscribed to last year as a "de-facto metaobject standard", meaning that any future standard would surely include these functions (which were almost entirely "introspective") ;;; First, start this guy out as a plain old 'standard-class' class. > (defclass enumerated-object () ((instances :initform nil :allocation :class :accessor class-instances))) # > (defclass enumerated-class (standard-class) ((clos::direct-superclasses :initform (list (find-class 'enumerated-object)) ;overrides value in ; STANDARD-CLASS ))) # > (defmethod clos-system:validate-superclass ((class enumerated-class) (super standard-class)) t) # > (change-class (find-class 'enumerated-object) (find-class 'enumerated-class)) # > (defclass frob () ((z :initform nil :documentation "Zome Zlot")) (:metaclass enumerated-class)) # > (clos:class-direct-superclasses (find-class 'frob)) (#) > (defmethod initialize-instance :after ((x enumerated-object) &rest w) (declare (ignore w)) (push x (class-instances x))) # > (setq x (make-instance 'frob)) # > (setq y (make-instance 'frob)) # > (class-instances x) (# #) > -- JonL --