[rucksack-devel] Re: SHARED-INITIALIZE calling (SETF SLOT-VALUE-USING-CLASS)

Pascal Costanza pc at p-cos.net
Sun Sep 3 22:28:58 UTC 2006


Hi Arthur,

I had exactly the same issue some time ago. The surprising thing is  
that a CLOS implementation is actually allowed not to use (setf slot- 
value-using-class) for object initialization, though the part that  
specifices this is somewhat tricky to find. Check out the notes  
section of shared-initialize in the HyperSpec, there it is specified  
under what circumstances (setf slot-value-using-class) can be  
circumvented (although this part actually doesn't explicitly refer to  
the MOP).

My solution was to create a new default super class for my own  
metaclass, ensure that it is used instead of standard-object, and  
then specialize shared-initialize accordingly. The following is taken  
from ContextL, and is just a straightforward implementation of the  
shared-initalize specification. Feel free to reuse it.

#+(or lispworks (and mcl (not openmcl)))
(defmethod shared-initialize ((object special-object) slot-names  
&rest all-keys)
   (declare (dynamic-extent all-keys))
   (let ((class-slots (class-slots (class-of object))))
     (loop for slot in class-slots
           for slot-initargs = (slot-definition-initargs slot)
           when slot-initargs do
           (multiple-value-bind
               (indicator value)
               (get-properties all-keys slot-initargs)
             (when indicator
               (setf (slot-value object (slot-definition-name slot))  
value))))
     (if (eq slot-names 't)
       (loop for slot in class-slots
             for slot-name = (slot-definition-name slot)
             unless (slot-boundp object slot-name) do
             (let ((slot-initfunction (slot-definition-initfunction  
slot)))
               (when slot-initfunction
                 (setf (slot-value object slot-name) (funcall slot- 
initfunction)))))
       (loop for slot-name in slot-names
             for slot = (find slot-name class-slots :key #'slot- 
definition-name)
             unless (slot-boundp object slot-name) do
             (let ((slot-initfunction (slot-definition-initfunction  
slot)))
               (when slot-initfunction
                 (setf (slot-value object slot-name) (funcall slot- 
initfunction)))))))
   object)

Note that I intentionally do not use (setf slot-value-using-class)  
here, but (setf slot-value) because otherwise this would break in  
some implementations. (I don't remember which one it was.) The  
effect, however, is that (setf slot-value-using-class) will  
ultimately be called - and then it works correctly. Don't ask me  
why... ;)

I hope this helps.


Pascal

On 3 Sep 2006, at 23:45, Arthur Lemmens wrote:

> Hi Pascal,
>
> While working on Rucksack I noticed that Lispworks (5.0) does not
> seem to call (SETF SLOT-VALUE-USING-CLASS) for the slots that it
> initializes in SHARED-INITIALIZE, whereas SBCL (0.9.16) *does*
> call (SETF SLOT-VALUE-USING-CLASS) in that situation.
>
> Have you ever noticed this difference?  Can you confirm it?  Do you
> know if the MOP specifies one way or the other?  Can you think of a
> way to get Lispworks behave like SBCL, or the other way round?
>
> Which is the better approach, according to you?  I was a bit surprised
> when I found out that Lispworks' SHARED-INITIALIZE did not call
> (SETF SLOT-VALUE-USING-CLASS), but then I programmed my way around it
> and forgot about it.  Until SBCL users started testing my nifty new
> indexing and schema update features for Rucksack, and complained about
> stack overflows ;-)
>
> Thanks for any insights you may have on this subject,
>
> Arthur
>
>

-- 
Pascal Costanza, mailto:pc at p-cos.net, http://p-cos.net
Vrije Universiteit Brussel, Programming Technology Lab
Pleinlaan 2, B-1050 Brussel, Belgium







More information about the rucksack-devel mailing list