I received a couple of points in feedback regarding
Pascal Costanza, the observation that there's
already a prototype-based dispatch system present in the
quasi-standard CL MOP; the key is to view all the prototype objects as
singletons, and to use introspection to manage delegation and the
as the actual object. Thus (any mistakes are mine, not Pascal's):
(defun clone (o) (let* ((scs (sb-mop:class-direct-superclasses (class-of o))) (new (make-instance 'standard-class :direct-superclasses scs))) (sb-mop:finalize-inheritance new) (sb-mop:class-prototype new))) (defun add-delegation (o d) (let ((scs (sb-mop:class-direct-superclasses (class-of o)))) (reinitialize-instance (class-of o) :direct-superclasses (list* (class-of d) scs))))
I don't think that this works in quite the same way as a traditional prototype-based system, mind you: here, a cloned object inherits all the behaviours provided by delegation, but not the behaviours from the cloned object itself. It's pretty close, though, and might help those to whom all this is new (but who are intimately familiar with the CLOS MOP – hm, actually, the intersection of those two sets might be a little small) get a bit of a handle on this.
Secondly, Lee Salzman was kind enough to get in touch, and we had a
conversation about his thesis and his reflections on that work. I'll
paraphrase, so again any misrepresentation is mine, but regarding the
question at the end of my
previous post about the
semantics of redefinition, Lee was quite clear that the expectation
was that previously-cloned objects should retain their previous
behaviour, even if the original object is later updated (in prototypes
and multiple dispatch terms, even if the original method is
redefined). In other words, the
??? is indeed expected by
prototype-oriented programmers to be
Lee also said that, in his subsequent experience, he has come to believe that class-based systems are a necessity – particularly in image-based systems (where there is a persistent world). He's happy with prototypes as a mechanism in a world with static programme descriptions, where you can just edit the source code, then compile and run the programme, but believes that directly modifying running programmes makes classes or some equivalent abstraction necessary. I'm not sure I completely understand this point (though I'm fairly convinced by now that I don't much like the semantics of method redefinition in a world with long-lived objects), but I'm still waiting for a good example to highlight the advantages of prototype-oriented programmes.
Meanwhile, what does this imply for the implementation of prototypes
with multiple dispatch within the extended CLOS metaobject protocol?
Defining a new method specialized on an must override any existing
behaviour for that object, but must leave unchanged the previous
behaviour for any clones; that therefore implies that the generic
function cannot discard the old method, as it must remain applicable
to any clones. The consequences of this include: two prototype
specializers, specialized on the same object, must not be considered
to be the same specializers (otherwise the standard semantics of
method definition would replace the old method with the new); and that
the specializers must be annotated with the method that they belong to
(so that it is possible to compute for a given specializer and
argument whether that argument is acceptable to the specializer,
remembering that the acceptability of an object to a prototype
specializer in this world is primarily a function of the object
itself). One piece of good news: the CLOS MOP already provides a
mechanism for associating specializers with methods, through the
generic function, so that's at least some of the battle.
All of this merits a fuller description, a reference implementation, and some example code using it. I'm working on the first two, aiming to top up my all-important publications list by presenting at some conferences (and also helping to justifying my attendance); I'd love to hear about ideas for the third...