[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Further Reaction to MOP

In my last message I expressed some concerns about the proposed
meta-object protocol. In this message I will express one of those concerns
more clearly. Lest anyone begin to fear that I oppose the proposal, let me
hasten to remark that I believe we need to know as precisely as we can the
limitations of any meta-object protocol before we adopt it.

When Gregor first explained to me his philosophy of the meta-object
protocol - before the draft was available - he said that it was the set of
objects on which the metacircular interpreter for CLOS operated.  He went
on to say that the MOP would talk about a set of generic functions,
methods on which could be defined along with other meta-objects to modify
the behavior of the interpreter. I took this a little too literally and
concluded that a ``meta-object'' is either one of these generic functions
or one of the objects on which those generic functions operated. Thus, the
meta-object protocol was a set of objects, a set of generic functions, and
a set of relationships among when and how those generic functions were
invoked.  In other words, to specify the protocol, one had to specify
those three things.

Gregor corrected me on this, and I learned that the generic functions and
the relationships among when and how they were invoked were the protocol,
and that the meta-objects are defined separately. To alter the style of
the object system, one needed to define new meta-objects and new methods
on those generic functions operating on those new meta-objects.

This led me to believe that the generic functions would be truly generic,
extracting information out of the meta-objects to determine further actions.
That is, I imagined that it was intended that any wild variant on
CLOS could be created with the definition of some wild meta-objects and
methods on the supplied generic functions.

Well, maybe you can do that, but the generic functions in the current
protocol have too many assumptions built into them.

I assume that all variants on CLOS definable with the meta-object protocol
should include: classes, generic functions, inheritance, instantiation,
and methods. I assume some variants might not include: frame/slot
structure, qualifiers on methods, named objects, multiple inheritance, or
linearized inheritance.

Some of the generic functions in the MOP don't seem to follow a strong
decompositional structure. For instance, ADD-NAMED-CLASS perforce assumes
that classes can be named, and its definition has built in the assumption
of the existence of slots. To a lesser degree its definition has built in the
assumption of multiple inheritance.

The existence of CLASS-FOR-REDEFINITION is built on the assumption
of the behavior of EQness over redefinitions. EXPAND-DEFMETHOD has built
in assumptions about qualifiers, EXPAND-DEFMETHOD has built in assumptions
about slots, options, and multiple inheritance.

If I were to build a variant on CLOS, I would abandon the current naming
scheme and use normal Lisp binding for naming. I would also probably
define a graph manipulation language and attach classes to the graph. An
explicit finalization protocol would optimize method lookup, etc.
Finally, I would add some encapsulation technology, probably abandoning
the current frame/slot format for instances.  Therefore, many of the
generic functions in this protocol are irrelevant to me.

Now, there is nothing wrong with having generic functions in the protocol
that have the various assumptions about the nature of the object-oriented
language built in, but I would have assumed that generic functions that
knew about these assumptions would be found in the information stored in
the metaclass and would have no names associated with them.  The
meta-object protocol would extract these functions and apply them.

The heart of the meta-object protocol seems to be parsing and creation.
Parsing of forms should be a simple matter of the user-level macro
invoking a parser from the correct metaclass.  Because we have such a
complex and powerful MAKE-INSTANCE protocol, I thought that the
meta-object protocol would be built on it, and, in fact, that
MAKE-INSTANCE would be formalized and be made the mainstay of the
meta-object protocol - it would represent the primary interpreter.  Recall
that there is a powerful technique for initialization to cause arguments
to be passed to allocation and initialization generic functions at various
times. I would have expected to see a protocol that looked like that and
was, therefore, more declarative in nature, putting information in
metaclasses to be extracted by methods on INITIALIZE-INSTANCE and
ALLOCATE-INSTANCE for those metaclasses. This would eliminate the need for
a wide variety of generic functions with a host of parameters that are too
specific to the default nature of CLOS.

For example, naming classes is an example of invoking a different 
ALLOCATE-INSTANCE method and a different INITIALIZE-INSTANCE method.

What we have, instead, is a fairly ad hoc protocol.  That is, it seems
that if one were to want to define a very different object-oriented
language - one in which there are no frame/slot-like structures, a
graph-oriented inheritance structure, mixed representations - one would
have to build a separate connected component to the hierarchy and define
another set of generic functions to handle the protocol.

Now, it might turn out that the initialization protocol is not good enough
to form the basis of the meta-object protocol, but attempting to use it as
such a basis would be a good test of it. And even though using the
initialization protocol would not simplify the situation much, it would
certainly unify it.