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

Re: Object creation discussion (at last!)

I have a lot of comments and questions about this proposal.  I
originally tried to work them in with the running text, but that proved
too cumbersome given the general nature of my comments.  What's more,
this message itself isn't all that polished.  I thought it would be
better to send it out now so that you would have an idea of what I was

My overall comment is that this proposal is a lot more complicated than
either of my previous proposals, in fact it doesn't seem to stress
simplicity at all.

Parts of this proposal provide important, useful and understandable
functionality, which I would like to see in CLOS.  Other parts add
considerable conceptual complexity and don't seem to add significant
functional gain.  The best example of this is the special method
combination type for initialize-instance.

After I send out this message I will begin working on another message
which lays out the framework of a proposal which incorporates all the
things I really like about your proposal.  I think that will be the best
way to make it clear what I have in mind.

My major objections are with:

*** special method combination for the initialize-instance 

The special method combination type for initialize instance adds
considerable conceptual overhead for very little functional gain.

I admit that the basic method combination rule is simple enough to
understand.  But there are other aspects of this method combination
types which will cause people to ask themeselves questions they will
have a hard time answering with any kind of simple model of this thing.

  - if I don't have to say &allow-other-keys here, why do I have to
    say it in the normal kind of method combination?

  - why is it that I can't count on the methods getting all the initargs
    if I use &rest in the lambda-list?  Note that this also robs useful
    functionality which exists everywhere else in Common Lisp.  Specifically,
    it makes the &rest args &allow-other-keys idiom not work.  This idiom
    is very useful for methods which want to process all the initargs in
    the init-plist in ways that makes those initargs interact.

  - If I redefine a initialize-instance method, will that effect the
    interpretation of all the :constructor lambda-lists involved?  Will
    all those :constructors get fixed?

*** the complex rules for interpreting the lambda-list of :constructors

These rules are just plain complicated.  In order to figure out what to
do, you need to know:

  The names of all the slots, inherited and local (simple enough).

  All the mappings to initargs of those slot names.  Inheriting
  this information is simple enough, but name mapping is confusing
  in general.

  All the :default-initargs inherited and local.  Once again,
  understanding the inheritance here is simple enough.

But putting all this together is pretty complicated.  Because it isn't
really three simple inheritance structures that are then combined.  I
don't think?  I think your rules may cover the following case, but I
don't believe its that simple to reason about.

(defclass foo () 
  (:default-initargs :bazola ()))

(defclass bar (foo)
     ((b :initarg :bazola)))

(defclass baz ()
  (:constructor make-baz (&key bazola)))

(defmethod initialize-instance ((a-baz baz) &key bazola)
  (setf (slot-value a-baz 'b) (list bazola (slot-value a-baz 'b))))

*** the overemphasis on getting speed out of the :constructors.

This proposal seems to be mostly focused on getting speed out of using
the :constructors.  While I agree that instance creation speed is
important, I am not sure that I like putting so much emphasis on doing
it using :constructors.

For one thing, from the user's point of view, I don't believe it is easy
to understand why constructors should be so much faster.  I don't
believe that the reasons why the :constructors are so much faster are

For another thing, the ability to be able to compile the :constructors
into something fast leaks all over.  The rule that says that particular
initialize-instance methods can't count on getting the entire set of
initargs is an excellent example of this "leakage".

Other specific questions:

- what arguments does allocate-instance get?  at one point you say:

    From Moon:
    2. Initargs that control storage allocation are defined by defining an
    allocate-instance method that accepts the initarg as an &key argument.
    For example, in systems with areas :area is an initarg for step 2.
    The standard does not require any initargs to exist for step 2.

but how does this work?  why don't all the allocate instance methods
also have to say &allow-other-keys.

Things that I like and agree with:

Since I have been focusing on things I don't like, it may not be clear
what I do like. Let me try to make explicit some of the major points I
like and agree with.

I like the functionality provided by the :default-initargs option.  The
next proposal I will submit has this feature in a slighltly more
CommonLispy syntax. 

I agree that the initargs to make instance are "more abstract" than slots.

I agree that constructors should call initialization methods.

I agree that it is important for instance creation to be fast.  I agree
that :constructors are the best known way of doing this.

I agree that there should be no defclass option which specifies an
initarg for all the slots.

I probably agree with other, more subtle things that I don't remember
right now.