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

Re: user interface macros

Your messages raise a number of issues.  In this message I attempt to
address them all, with the exception of simple typos and other obvious
screw-ups (I will correct those though).

This message is divided into two parts.  The first part addresses
comments about the nature of the macroexpansion specification and
tries to show my sense of what it is appropriate to be saying at
this time.  The second part deals with specific issues that were

ON THE NATURE OF THE GOALS (of this section as it relates to the whole)

    Date: Fri, 27 Apr 90 17:08:50 PDT
    From: Jon L White <jonl@lucid.com>

    To what end specify the macro expansions exactly?

These are good questions and ones I have spent some time wrestling with
as well.  In fact, as you yourself point out, the current draft attempts
not to say anything about the expansions themselves.  Instead, it tries
to talk only about the various calls that result from evaluation or
executing a macro.

The question then becomes why even bother to do that.  The main reason
is to allow user-defined metaobject classes to be instantiated by the
standard macros.  You want DEFCLASS to be able to create instances of
MY-CLASS, you want DEFMETHOD to be able to create instances of MY-METHOD

    Rather, I think the only point of mentioning the expansion of the
    definer "user interface" macros is that our experience with metaobject
    creations over the past two years, via portable constructs, *had* to
    be limited to these macros.

I don't have any idea what this sentence means.

The goal of this document is to specify the behavior of the anonymous
metaobjects -- that is what is powerful and interesting.  But, to do so
properly, requires that we say some things about the rest of the CLOS
mechanisms.  We need to talk about the macroexpansion layer for the
reasons mentioned above.  We need to talk about the name-->object
mapping layer because many user metalevel programs want to blend with
the name--> object mapping already used in `conventional' CLOS programs.
These aren't the most interesting parts, but they are essential to the
success of the whole.

What is perhaps unfortunate is that this round of work is starting with
macroexpansion -- that decision was made because that is the part of the
old document that was in the worst shape.  We just have to remember that
this isn't the part we really care about.  That we just need to do
enough ui macro stuff to enable the kinds of things users need to do as
mentioned above.

For example, Scott proposes a full-featured mechanism for metaclass
control over the parsing of DEFCLASS forms into calls to ENSURE-CLASS.
I have experimented with things like this in the past, and the one Scott
proposes is a nice one.  But, I don't think we want to specify this sort
of thing right now.  I feel like it is more than we want to get into,
especially given JonL's valid points that the uimacros are the least
important part of this whole thing.

I would rather do some combination of changing the specified behavior of
the ui macros and explicitly allowing this kind of implementation
specific extension.  I could be argued out of this, especially if
someone else wrote the relevant text (Scott has a start).

So, on the subject of extending the syntax of DEFCLASS, I propose:

  - remove the part about what happens when an option (any option) is
    specified more than once.  Just say it is not specified, that
    implementations are free to document their own behavior.

  - either
      - fix the :metaclass and :documentation class options and leave
        the stuff about the tail of the list (this is what I had in
        mind originally and failed to write)


      - make the class options (other than :default-initargs) pass
        the CADR

  - explicitly mention that implementations are free to have specific
    mechanisms for extending the behavior of the ui macros.

  - fix the stuff about order to say only:

       - the order of :default-initargs is preserved

       - and possibly that for unspecified slot and class options,
         they the specified ones and their order is preserved


    Date: Thu, 26 Apr 90 11:43 EDT
    From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>

    First fix the confusion of using "compile" both to mean "translate to
    machine code" and also to mean "write a file that can later be loaded
    and will produce similar objects."  You'll know you've got it right when
    the specification does not admit any difference between EVAL and calling
    the result of COMPILE.  You're concerned with the case of one Lisp or
    two (the compiling lisp and the loading/running Lisp), but you're not
    concerned with whether the representation of Lisp programs is
    S-expressions or machine code.  I suggest eliminating all use of the
    word "compile" except in the compound form "compile-file."

Yes, I was trying to head in this direction, but as we have all learned
it isn't so easy.  The part about allowing DEFGENERICs that appear in
compiled files to affect the way DEFMETHOD forms are processed is, of
course, what makes it hard.

I will give this another go.

    Date: Thu, 26 Apr 90 17:38:26 PDT
    From: David Gray <gray@lucid.com>

    Rather than "evaluates the initform", I would prefer that the wording be
    modified to make it clear that it is permissible for the compiler to
    substitute something that has an equivalent effect.  For example,
	    :INITFORM (* 2 5)
    could result in

How about "returns the result of evaluating the initform in the lexical
environment of the DEFCLASS form"?

    Date: Fri, 27 Apr 90 17:58 EDT
    From: Cyphers@STONY-BROOK.SCRC.Symbolics.COM,

	 User interface macro forms can be {\bit evaluated}, {\bit compiled}, or a
	 compiled macro form can be {\bit executed}.  

    This sentence is a bit confusing.  I think it meant to say
    "User interface macro forms can be {\bit evaluated} or {\bit compiled}
    and {\bit executed}."  Since that is true of all macros, I'm not really
    sure why it needs to be said at all.

The purpose of the sentence was to define the three terms.  I will try
and fix this as mentioned above.

    In the arguments to ENSURE-CLASS, this document has :DIRECT-SUPERCLASSES and
    :DIRECT-SLOTS where 89-003 has :SUPERCLASSES and :SLOTS.  Symbolics CLOS uses
    :DIRECT-SUPERCLASSES (based on mail with Gregor a few months ago) but :SLOTS.
    For consistency, :DIRECT-SLOTS would be better, but we've passed the point of
    being able to remove :SLOTS, although we could make :SLOTS mean :DIRECT-SLOTS.

    Although no document and no implementation uses :DIRECT-DEFAULT-INITARGS
    currently, it would be more consistent.

It's difficult for me to tell what you are asking for here.  The change
to :DIRECT-XXX was based on the mail you mention.   I really think these
are better names.  Unless someone complains I would like to leave these

	 A canonicalized default initarg is a list of three elements.
    Symbolics CLOS and 89-003 put the form before the function.  Why was the order
    gratuitously changed?

    Also, there needs to be provision for implementation additions (we use one),
    just as in the canonicalized slot specification.  Just allow the list to have
    more than three elements, where elements after the first three are
    implementation dependent.

I will change the order back and allow the lists to be longer.  But, for
  * I believe the order in draft 11 is better because it makes the
    implementation-specific `improvement' where you drop the form
    more straighforward.
  * I don't think making the lists longer is the most modular way
    to do the extension you mention.  Instead, another keyword
    argument/initarg which parallels this one should be used.

    The name in 89-003 and in Symbolics CLOS is generic-function-method-class.
    Why the gratuitous change?

Braino, I will change it back.
	 \item{\bull} The value of the {\bf :specializers} initarg is a list of the
	 specializer names for the method.  For {\bf eql} specializers, this is a
	 list in which the first element is the symbol {\bf setf} and the second
	 element is the result of evaluating the eql specializer form in the lexical
	 environment of the {\bf defmethod} form.  For any other kind of
	 specializer, this is the value from the {\bf defmethod} form with no
	 special processing done.
    It's too weird to make this a list of elements that are parameter specializers
    in one case and parameter specializer names in the other case.  89-003 p.3-69
    requires parameter specializers here, i.e. classes rather than class names.
    See also 89-003 p.3-16.  So not only is this weird, it's also a gratuitous

Actually, I don't think its weird, but I am willing to change it back.
I believe, as I alluded to before, that there are three layers.

  1) the macroexpansion layer
  2) the name to metaobject mapping layer
  3) the anonymous metaobjects (where the real CLOS behavior is)

The way this worked in 89-003 and the way you have it puts stuff from
layer 2 in layer 1, and that isn't modular.

	 \item{\bull} The {\it direct superclasses} argument to {\bf defclass}
	 becomes the value of the {\bf :direct-superclasses} keyword argument to
	 {\bf ensure-class}.

    We do this differently.  If the {\it direct superclasses} is NIL, then the
    metaclass is asked for the list of direct superclasses to be used, using
    class-default-direct-superclasses.  For STANDARD-CLASS, (STANDARD-OBJECT) is
    ENSURE-CLASS receives the actual list of direct superclasses.  In our way of
    defaulting these, it is possible for a metaclass to make classes which have no
    superclasses.  The result of class-default-direct-superclasses is a list of
    class objects even though the :direct-superclasses is otherwise a list of
    class names; this might be a mistake, but does allow for anonymous classes
    as default direct superclasses.

This is a similar issue.  Defaulting the superclasses doesn't seem to me
to be a macroexpansion issue.  It seems to me that defaulting the
superclasses is an essential part of the behavior of the raw object
system.  Once again though, I can live with it this way.

    Defining NULL to be the predicate that tests whether an environment is the
    run-time environment is not very abstract.  This could run into serious
    problems with future extensions that unify this environment with the
    &environment argument to macros or that implement more than just the run-time
    and compilation environments.  On the one hand, NIL might not be the only
    representation for the "ordinary" environment, and on the other hand, there
    might be several distinct environments that all have the property of
    containing classes that can be instantiated and methods that can be executed.

I agree with all of these comments.  What if we just added an argument
:COMPILE-ENVIRONMENT-P or something.  It would be true or false.  In
cases where it is true it would mean the some other information, passed
in implementation-specific keyword arguments had the real compile

    Date: Fri, 27 Apr 90 17:58 EDT
    From: Cyphers@STONY-BROOK.SCRC.Symbolics.COM,

    When defmethod calls ensure-generic-function, it must not supply the
    :lambda-list argument.  ensure-generic-function has to know the difference
    between a call from defgeneric (which always replaces the lambda-list),
    and a call from defmethod (which never replaces the lambda-list).
    Symbolics CLOS works as outlined in this message:

    Date: Fri, 27 Apr 90 17:08:50 PDT
    From: Jon L White <jonl@lucid.com>

    A gap in the current definition of ENSURE-GENERIC-FUNCTION?

Based on the comments you have sent, here is a strawman.  What if we
have ENSURE-GENERIC-FUNCTION accept two keyword arguments: :LAMBDA-LIST

The :LAMBDA-LIST argument will be passed in by DEFGENERIC.  Its value
will the the value specified in the macro form.  Its presence (or
non-nullness) will indicate the call was from DEFGENERIC.

The :METHOD-LAMBDA-LIST argument will be passed in by DEFMETHOD.  Its
value will be the unspecialized lambda list from the macro form
(what you get by calling extract-lambda-list).  Its presence (or
non-nullness) will indicate the call was from DEFMETHOD.

This means that special processing will happen inside of ENSURE-GF and
initialization when DEFMETHOD creates a generic function, but this
scheme should make all the information each of you wants available.