From: Chris Double
Subject: CLOS :allocation slot types
Date: 
Message-ID: <wkaenff82r.fsf@double.co.nz>
CLOS has :class and :instance allocation types for slots. I'd like to
have an :each-subclass type, where :each-subclass allocation is like
:class except every subclass of the class gets a storage location for
the slot, shared by its direct instances. For example:

(defclass base ()
  ((slot1 :allocation :each-subclass)))

(defclass derived (base))

(setq a-base1 (make-instance 'base))
(setq a-base2 (make-instance 'base))
(setq a-derived1 (make-instance 'derived))
(setq a-derived2 (make-instance 'derived))

(setq (slot-value a-base1 'slot1) 'base-value)
(slot-value a-base1 'slot1) => 'base-value
(slot-value a-base2 'slot1) => 'base-value
(slot-value a-derived1 'slot1) => 'unbound

(setq (slot-value a-derived1 'slot1) 'derived-value)
(slot-value a-base1 'slot1) => 'base-value
(slot-value a-base2 'slot1) => 'base-value
(slot-value a-derived1 'slot1) => 'derived-value
(slot-value a-derived2 'slot1) => 'derived-value

Dylan has an each-subclass allocation type and I'm transferring some
Dylan code to Lisp. Is there any equivalent functionality in CLOS, or
is it possible to implement using the MOP? Any advice on implementing
something similar would be appreciated.

Chris.

From: Robert Monfera
Subject: Re: CLOS :allocation slot types
Date: 
Message-ID: <3854FD3B.CD5923E@fisec.com>
Hi Chris,

If you inspect the definition of a class (i.e., a class metaobject), you
will see that the list of subclasses is stored in a slot named
clos::direct-subclasses.

You could create a new class metaobject class DYLAN-CLASS by subclassing
standard-class, with an extra slot SLOT-VALUES-FOR-SUBCLASSES for
carrying the slot-values: a 2-dimensional array (subclass-allocated
slots x subclasses).

You need to specialize (override) the behavior of slot-value-using-class
for cases where your class is the instance of your new metaclass, and
the slot is subclass-allocated.  To make it easy, you would need to
create new slot definition metaclasses
(SUBCLASS-ALLOCATED-DIRECT-SLOT-DEFINITION and
SUBCLASS-ALLOCATED-EFFECTIVE-SLOT-DEFINITION) to carry the effective and
direct slot definition metaobjects in your new class metaobject class.
These would need to inherit from standard-direct-slot-definition and
standard-effective-slot-definition.

In order to use specialized direct and effective slot definition
metaobjects, you need to specialize for direct-slot-definition-class and
effective-slot-definition-class.  Take care, ACL uses the formal
parameters as defined by AMOP, while LW uses a second required parameter
instead of the &rest argument.

To propagate direct-slot-definition values to effective-slot-definition
ones, you may or may not want to define an :after-method for
finalize-inheritance, specialized on your new class metaobject class.

To speed up the access of values stored in your array stored in
SLOT-VALUES-FOR-SUBCLASSES, you may want to store a column number in
each of your effective slot definition.

Because the list of subclasses may change, you need to have a
specialized method for add-direct-subclass and remove-direct-superclass.

To put the last nail in the coffin, you need a macro that works
similarly to defclass except that it uses or allows you to use the new
slot SLOT-VALUES-FOR-SUBCLASSES in your DYLAN-CLASS.

Better yet, you may opt to spit the array of SLOT-VALUES-FOR-SUBCLASSES
so that every subclass-allocated slot definition carries one vector,
where the elements represent the order of subclasses.  This helps avoid
the indexing, and may avoid having to use a custom macro, because you
would not need extra class slots anymore.

If the above sounds overwhelming, then AMOP is a must to read.  I can
send you some code snippets for most of the steps, although I used MOP
for different purposes.  I didn't have much time to type it up, so there
may be ommissions or inaccuracies - feel free to ask if something does
not seem to make sense.

Regards
Robert
From: Martin Simmons
Subject: Re: CLOS :allocation slot types
Date: 
Message-ID: <01bf4661$b5dced30$35ee58c0@cutler>
It looks like :each-subclass slots would be like automatically redefining a
:class slot in each subclass, i.e.

(defclass base ()
  ((slot1 :allocation :class)))

(defclass derived (base)
  ((slot1 :allocation :class)))

If so, it would be nice to leverage off the existing implementation of
:class allocated slots.

Probably the simplest and most portable way would be to do this at the
macro level.  MOPpetry would be another approach, but AMOP doesn't cover
:class allocated slots so there is a lack of standardization about when and
how they are handled anyway.

-- 
Martin Simmons, Lisp Group, Harlequin Limited
······@harlequin.co.uk
From: Robert Monfera
Subject: Re: CLOS :allocation slot types
Date: 
Message-ID: <38569BB0.2FFAE3C4@fisec.com>
Martin Simmons wrote:

> It looks like :each-subclass slots would be like automatically redefining a
> :class slot in each subclass, i.e.
>
> (defclass base ()
>   ((slot1 :allocation :class)))
>
> (defclass derived (base)
>   ((slot1 :allocation :class)))
>
> If so, it would be nice to leverage off the existing implementation of
> :class allocated slots.

Yes, it can lead to a much simpler solution if no multiple inheritance
is used.

Robert