Re: MOP: class-level variables, prototypes

Martin Simmons <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
>>>>> On Wed, 2 Apr 2025 07:24:33 -0400, Christopher Stacy (as cstacy at dtpq dot com) said:
> 
> Today I am using :CLASS allocated slots and have learned something I 
> wanted to pass on.
> 
> Most documentation seems a little vague on the point, but indeed, you're 
> only going to get the one slot in the final object. Maybe this is 
> obvious, but if you hoped that multiple subclasses could each get their 
> own :class allocated slot from your mixin that mentioned it, no dice. 
> All the subclasses are going to share that one slot. This is what is 
> meant by "class allocated slots cannot be inherited". Of course you 
> inherit the slot, it's that you don't inherit a new slot that will be 
> class allocated. Even though your classes have nothing to do with each 
> other, all will  be sharing that very one slot from the superclass.

Yes, https://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm tells
you how to get a separate slot in a subclass:

"If allocation-type is :class, a shared slot of the given name is allocated in
the class object created by this defclass form. The value of the slot is
shared by all instances of the class. If a class C1 defines such a shared
slot, any subclass C2 of C1 will share this single slot unless the defclass
form for C2 specifies a slot of the same name or there is a superclass of C2
that precedes C1 in the class precedence list of C2 and that defines a slot of
the same name."

Another gotcha is that defclass only initializes the slot if it is unbound, so
redefining the class with a different :initform will have no effect after
that.

> Classes have a prototype which is like the instance, and you can get 
> your hands on it and it will run methods that don't side-effect the 
> (non-existent) instance. It will also have any :class allocated slots, 
> and they will be initialized. So methods can side-effect those. Before 
> these handy tricks will work, the class must be finalized. CLOS is only 
> required to ensure they are finalized when you call make-instance.  You 
> can call a MOP function to finalize them when you want, instead.

It has never been clear to me whether the class slots are guaranteed to have
been initialized in the prototype, but they probably are.

However, the following shows that they might not be reinitialized until
make-instance (shared-initialize really) is called:

(defclass foocclass () ((x :allocation :class :initform 10)))

(clos:finalize-inheritance (find-class 'foocclass))

(slot-value (clos:class-prototype (find-class 'foocclass)) 'x)  =>  10

(slot-makunbound (make-instance 'foocclass) 'x)

(slot-value (clos:class-prototype (find-class 'foocclass)) 'x)  =>  unbound-slot error

(slot-value (make-instance 'foocclass) 'x)  =>  10

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
[email protected]
http://www.lispworks.com/support/lisp-hug.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.