[comp.lang.clos] Delegation in CLOS?

ziggy@hx.lcs.mit.edu (Michael R. Blair) (03/22/91)

I am trying to implement delegation atop CLOS using the meta-object
protocol. Has anyone else attempted this with any degree of success?

I am slowly becoming convinced that the meta-object protocol provides
enough handles into the CLOS system to allow variations on the
CLASS/INSTANCE view of OOPS, but that there may be too few handles to
implementing DELEGATION-based OOPS. I can, of course, rationalize why
CLOS might be class/instance biased but I am disappointed that the
meta-object protocol doesn't seem to be headed toward loosening this
bias. Of course, I am a meta-object neophyte so don't assume that I
really know what I'm talking about... I am suffering more from an
emotional response than from a technical dilemma: the pieces lay
clearly before me and yet I do not see how to assemble them to do my
biding. Anyone care to slap me awake by saying ``Obviosly, what you
should do is <fill in the blank>''.

I have a few half-baked approaches I have considered but they seem to
lead to dead-ends. Here is my current thinking:

[0] If I could allocate only direct slots in an instance along with a
    DELEGATE(S) slot to point to other objects to delegate through,
    then I could use slot-missing as a handle for delegating to find
    the remaining effective-slots. This lets me declare superclasses
    as usual to get all the lovely method inheritance for free.
 ---BUG: I see no elegant way to intercept the allocation to allocate
    space for only the direct slots. This also gives me no nice way to
    resolve one-name-several-slots problems (slot shadowing) while
    allowing access to all slots of a given name.

[1] Failing that, I could intercept DEFCLASS on instances of the
    DELEGATES meta-class to make the slot definitions actually
    turn into just reader and writer methods closed over a shared
    local variable. Something vaguely like:

    ;;; defines a ``slot'' within the instance me
    (LET ((storage-cell '<we-dont-need-no-stinking-slots>))
      (defmethod reader ((object (eql me))...args...)
        storage-cell)
      (defmethod writer ((object (eql me))...args...)
        (setq storage-cell ...)))

    Presumably some wild contortions on COMPUTE-APPLICABLE-METHODS and
    COMPUTE-DISCRIMINATING-FUNCTION could allow the use of
    CALL-NEXT-METHOD to search through all slots of the same name
    until the desired one is located... maybe hashing on the delegate
    instance to find the appropriate reader/writer.
 ---BUG: This looks unduly complicated... loads of meta-object surgery
    to by-pass the class/instance bias of CLOS would be needed, which
    I am not sure is logically necessary.

[2] Give up and define a DELEGATE meta-class whose instances always have
    superclasses null. Do all the inheritance explicitly through the
    DELEGATES slot.
 ---BUG: How then could method inheritance be done? Looks like a total loss.

Anyone have any more elegant approaches?

 ziggy@lcs.mit.edu (Michael R. Blair)