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

MOP Comments (Repost) - 2 3 4 5a



    Date: Wed, 09 Dec 87 11:00:00 MST
    From: kempf%hplabsz@hplabs.HP.COM

Thanks for your comments.  There are so many of them that I won't try to
address all of them in this message.  This message include comments on
points 2, 3, 4 and 5a.

    2) "class-prototype"

    There is no explicit definition of what a class prototype is in the MOP.
    Why should a class prototype be any different than an instance of a
    class object of the particular metaclass required?

This is just an omission in the current document.  All a class prototype
is is an instance of the given class that can be used for method lookup.
So for example, when calling a generic function like expand-defclass,
you can use class-prototype as follows:

  (expand-defclass (class-prototype (class-named 'standard-class))
                   'foo
                   '()
                   '((a :initform 1) (b :initform 2))
                   '()
                   '())

A legal definition of class-prototype is:

 (defun class-prototype (class) 
   (allocate-instance class))

but the idea was that class-prototype would always pass back the same
instance again and again and in this way prevent needless consing.

    3) Classes in the CLOS Kernel

    There is no slot for the dispatcher code in STANDARD-GENERIC-FUNCTION.
    Is the idea to have different method dispatch protocols implemented by 
    specializing STANDARD-GENERIC-FUNCTION, with COMPUTE-DISCRIMINATOR-CODE 
    returning the specialized code? The problem with this is that, for 
    optimization purposes, it may be desirable to have the dispatcher on a 
    STANDARD-GENERIC-FUNCTION instance change. For example, if all the methods 
    on the generic function only have built-in classes as parameter specializers, 
    then the dispatcher need not check if the class of the arguments is a user 
    defined class, since, if it's not a built in class, then an error should be 
    signalled. This avoids the overhead of checking whether the arguments are
    of a user defined class. Given the MOP as outlined in the document, the
    only way this could be achieved is to have a different kind of generic
    function, and that means that the generic function object would not be
    EQ before and after a method which has user defined classes in the
    parameter specializer list is added. One way to fix this would be to do a
    CHANGE-CLASS  on the generic function object, but that seems somehow
    to be less than optimal, since it seems to be just fixing up the problem
    afterwards.

I guess I don't understand this point at all.  I don't see the relation
between the optimization you mention and the a slot for the
discriminator code or the class of the generic function.  Certainly the
discrimintor code will be computed and stored 'somewhere' in the generic
function, we just didn't see the need to specify a slot or an intrinsic
accessor for it.

It seems to me that the relevant code is:

(defmethod add-method (..)
  .. (compute-discriminator-code gf) ..)

(defmethod remove-method (..)
  .. (compute-discriminator-code gf) ..)

(defmethod update-generic-function (..)
  .. (compute-discriminator-code gf) ..)

Given that, compute-discriminator-code can produce a piece of
discriminator code that is optimized in the ways you mentioned.
Certainly I would expect that the standard method on
compute-discriminator-code would perform this optimization.

    4) Editorial Comment: Location of Named Class Definition, Slot Parsing,
       and Inheritance Sections

    These three sections should probably be moved so that they are in closer
    proximity. Perhaps even making the slot sections a subset
    of a section on named class definition, since they must logically precede
    class definition. Most helpful would be a 1-2-3, step by step description
    of what happens when in class defintion, and which generic functions are
    involved.

In the latest draft these have been moved closer together and all the
stuff having to do with methods and generic functions was put together.

    5) Class and Method Definition Syntax

I want to split this into two parts, I am only including the parts of
this that I am responding to in this message.

    There is a fundamental tension in the document between the desire to
    have DEFCLASS and DEFMETHOD work for user defined metaclasses 
    as well as the defaults, and the lack of the ability to do certain things.

    Two examples:

I am only responding to the first one.

    a) Suppose I want to define a kind of slot which asks the user for a
    value upon access (ASK-SLOT). Many AI languages have this kind of thing.
    One way to do it would be to add a :SLOT-CLASS option to the slot-spec
    syntax, but there are likely to be other areas where users will want
    to make semantic extensions to class definitions, which will then need
    to be reflected in the syntax.

    This tension can be resolved in a number of ways:

    1) Drop the :METACLASS option for DEFCLASS and :METHOD-CLASS option for
    DEFGENERIC. Thus, if people want to implement metaclasses requiring
    syntactic changes will have to supply their own macros to do it. The generic
    functions in the MOP should be sufficient to support this, however, and
    the procedure for doing it should be outlined. The disadvantage would
    be syntactic divergence between CLOS syntax and that used by implementors
    of other metaclasses (but see the section below on how to handle
    the default CLOS metaclasses for a possible mitigation).

    2) Extend the MOP for DEFCLASS parsing and the DEFGENERIC syntax to handle
    the cases outlined above (and others which could potentially be found).

    Specifically, addressing a), functions for registering permitted syntactic
    extensions to the DEFCLASS parser are needed. This would provide a limited
    ability to extend the DEFCLASS syntax, in areas where users are most likely
    to want it. Here's a shot at a specification:

    ADD-DEFCLASS-SLOT-OPTION _metaclass_ _option_

    Causes _option_ (a symbol) to be registered with the DEFCLASS parser
    as a valid slotd option for classes of metaclass _metaclass_ (a class
    object). The option will be added to the normalized slot specification
    during slot parsing.

    ADD-DEFCLASS-CLASS-OPTION _metaclass_ _option_

    Causes _option_ (a symbol) to be registered with the DEFCLASS parser
    as a valid option for classes of metaclass _metaclass_ (a class object).
    The option will be added to the _options_ parameter of EXPAND-DEFCLASS.

Extending the defclass and slot options for a class already works.  I
think the sentence "If there are any syntactic errors in the defclass
form an error is signalled" is confusing.  All this sentence is saying
is that it takes the cadr of the defclass form and makes it be the name,
the caddr and its the supers, the cadddr is the slots and the cddddr is
the options.  If for some reason it can't do that minimal parsing an
error is signalled.  

Given that all further parsing is in the mop protocol.  Extended options
are handled by the slot-parsing protocol and legal-class-option-p.

For example, to define a metaclass that supports a :slot-class slot
option:

(defclass my-class (standard-class)
    ())

(defmethod slot-description-class ((class my-class) specification)
  (symbol-class (getf (cdr specification)
                      :slot-class
                      'standard-slot-description)))

(defclass my-slot-description (standard-slot-description)
    ())

(defmethod :after initialize-instance ((slotd my-slot-description)
                                       &key slotd-class)
   ())


To define a metaclass that supports a new :foo class option.

(defmethod legal-class-option-p or ((class my-class) option)
  (and (listp option)
       (eq (car option) ':foo)))
-------