Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 21 Jan 87 00:33:21 EST Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 19:10:59 PST Return-Path: <@SUMEX-AIM.STANFORD.EDU:SHOCHI.ISHIDA@NTT-20> Received: from SUMEX-AIM.STANFORD.EDU by Xerox.COM ; 20 JAN 87 19:10:07 PST Received: from NTT-20 by SUMEX-AIM.STANFORD.EDU with Cafard; Tue 20 Jan 87 19:05:12-PST Date: Wed, 21 Jan 87 10:39:55 From: toru Subject: questions from JEIDA Object Oriented Programming WG To: commonloops.pa%xerox.com@SUMEX-AIM.STANFORD.EDU cc: ida%todai%NTTLAB.NTT@NTT-20.ARPA, shochi.ishida@NTT-20.ARPA Message-ID: <12272551692.34.SHOCHI.ISHIDA@NTT-20.NTT.JUNET> Let us ask a few more questions. <<4>> Consider the following example: (defstruct (foo (:class class)) (a 1)) (defstruct (bar (:class class) (:include foo)) (a 10)) (defstruct (baz (:class class) (:include bar))) (defstruct foo (a 1)) (defstruct (bar (:include foo)) (a 10)) (defstruct (baz (:include bar))) What should be happened in CommonLoops when the followings are evaluated: (baz-a (make-baz)) (bar-a (make-baz)) (foo-a (make-baz)) At present, we have observed the followings. baz-a... invalid(symbolics, Vaxlisp,kcl) 1(symbolics),10(kcl) bar-a... 10(symbolics,Vaxlisp,kcl) 1(symbolics),10(kcl) foo-a... 10(symbolics,Vaxlisp),1(kcl) 1(symbolics,kcl) In Vaxlisp: (defstruct (bar (:include foo)) (a 10)) is invalid, because the slot is already defined in foo. <<5>> PCL does not handle multi-methods when those arities are different. For example: (defmeth foo ((x p))) (defmeth foo ((x p) (y q))) Let us know what kind of discussions were there? Thank you. Toru Ishida shochi.ishida%ntt-20@sumex-aim.arpa -------  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 20 Jan 87 18:12:49 EST Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 13:20:08 PST Date: 20 Jan 87 13:18 PST From: Gregor.pa@Xerox.COM Subject: Re: Bug(?) in defmeth and number of arguments In-reply-to: Frank Halasz 's message of Tue, 20 Jan 87 15:09:08 CST To: halasz@mcc.com cc: Gregor.pa@Xerox.COM, CommonLoops.pa@Xerox.COM Message-ID: <870120-132008-2301@Xerox> Date: Tue, 20 Jan 87 15:09:08 CST From: Frank Halasz Okay. But you haven't specified what happens when you do define methods with the same name but conflicting number of required arguments. Actually, what it should do is signal an error when you try to add a method with a different number of required arguments than the methods that are already there. Then the user can user REMOVE-METHOD to remove any methods they want to remove and rebuild the generic function. Of course a particular programming environment might offer a proceed-type which would allow the user to edit all the methods of the generic-function "in parallel" and then add them "in parallel", this would save the user having to remove all the methods from a generic-function, then going to each method, editing it and redefining it. Specifying this sort of interface is, of course, outside the scope of the language definition.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 20 Jan 87 18:12:34 EST Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 13:11:48 PST Return-Path: <@MCC.COM:halasz@mcc.com> Received: from MCC.COM by Xerox.COM ; 20 JAN 87 13:10:12 PST Received: from milano.sw.mcc.com by MCC.COM with TCP; Tue 20 Jan 87 15:10:08-CST Received: from geza (geza.ARPA) by milano.sw.mcc.com (4.12/STP) id AA17021; Tue, 20 Jan 87 15:09:21 cst Date: Tue, 20 Jan 87 15:09:08 CST From: Frank Halasz Posted-Date: Tue, 20 Jan 87 15:09:08 CST Message-Id: <8701202109.AA11957@geza> Received: by geza (1.1/STP) id AA11957; Tue, 20 Jan 87 15:09:08 CST To: Gregor.pa@Xerox.COM, halasz@MCC.COM Subject: Re: Bug(?) in defmeth and number of arguments Cc: CommonLoops.pa@Xerox.COM From Gregor.pa@Xerox.COM Mon Jan 19 18:52:17 1987 Date: Thu, 15 Jan 87 16:04:59 CST From: Frank Halasz It appears that you cannot have methods with the same name but different numbers of arguments. For example, CommonLoops will not work with the following defmeths. That's right. All methods must have the same number of required arguments. Okay. But you haven't specified what happens when you do define methods with the same name but conflicting number of required arguments. The current implementation is that the minimum number of arguments used so far is the "correct" number of arguments for a method of a given name. This seems like a bad choice. Say you define a 1-argument method, and then later decide it really should be a two argument method. There is no way to "redefine" the method to be a 2-arg beast. Seems like some other conflict resolution scheme is needed. "Last defined" seems better than "minimum", but some way of allowing the programmer to specifying the resolution principle seems best. -- Frank  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 20 Jan 87 17:58:30 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Jan 87 14:29:36 PST Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 13:15:51 PST Date: 20 Jan 87 13:15 PST From: Gregor.pa@Xerox.COM Subject: Re: New version of define-method-combination In-reply-to: Danny Bobrow 's message of 20 Jan 87 12:11 PST To: Bobrow.pa@Xerox.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870120-131551-2295@Xerox> Here are my comments about Danny's proposed changes to method combination. Some of these comments actually apply to Moon's last revision also. Basically, I am commenting on the contents of Danny's message as a whole without being too careful about where the particular ideas came from. I agree with the elimination of the simple form of define-method-combination. I think this is a positive step towards streamlining this part of the proposal. I am not sure that method-group-specifier options are really needed. In my most streamlining mood, I would suggest removing them. In a less streamlining mood, I like the new :required method-group-specifier option. I like the new :around method-combination option. I think this will make it easier for people to deal with :around methods. We might want to think about changing the "sense" of this option, or changing the default, so that aroundification happens by default. I understand the motivation for allowing a predicate instead of the templates. I think that motivation should be presented explicitly since without it, the predicate seems like uneeded complexity. I like changing the name of the :around keyword to make-method-call to :call-next-method. I don't really like the fact that information is communicated to make-method-call using special variables. I thought having make-method-call be a lexically bound function was much more elegant, and much more in keeping with the lexically scoped way of doing things. I don't really like method-combination-error and invalid-method-error. They just add complexity to this part of the proposal to make up for the fact that the error system has not been adopted yet. There are many parts of the object system which want to signal special kinds of errors, we don't have special functions for all of them. Perhaps what we should do is assume the error system is going to be accepted (seems likely), and then talk about what kind of error is signalled by each part of the object system. This seems more reasonable than introducing a bunch of error functions which will just have to be removed when the error proposal is adopted, or worse yet supported as backwards compatibility for life. I still don't like calling the default kind of method combination standard. I would prefer if we called it default, in fact, it might be better to call it daemon-with-around or some other descriptive name. What method combination types will we say are defined? There is a definite package problem here. We should probably include some comment on it in the spec. A user can't very well go and do define-method-combination of lisp:and. If they do it "differently" they could break the system or some other application. I think the examples should be re-worked to show users defining method-combinations whose names are symbols which are not in the lisp package.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 20 Jan 87 15:37:01 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 20 Jan 87 12:20:45 PST Received: from Cabernet.ms by ArpaGateway.ms ; 20 JAN 87 12:21:11 PST Date: 20 Jan 87 12:11 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: New version of define-method-combination To: common-lisp-object-system@SAIL.STANFORD.EDU cc: Bobrow.pa@Xerox.COM Message-ID: <870120-122111-2214@Xerox> The following is an alternate version of define-method-combination. It has the following properties: 1) There is only one define-method-combination form. It allows easy support of around methods, and supports error checking. Defining simple combinations is easy and concise. 2) There is no lambda-list. It also omits the keyword :order from the method specifier. defgeneric-options is extended to store parameters in the generic function. This can be used to support features like reversed order for combination if desired. 3) It is syntactically distinguishable from the current Flavors version of define-method-combination, and hence allows backwards compatiblity. 4) It uses the keyword :call-next-method instead of :around in make-method-call. This eliminates confusion with respect to use of this keyword with primary methods, and with respect to the new :around keyword in method-combination options used to support around methods. Thus (make-method-call primary :around t) becomes (make-method-call primary :call-next-method t) This renaming needs to be carried through to the functi chapter. Text that looks similar to that in the concep chapter was in fact taken from there, and no changes were made in most paragraphs. I am recommending that we include this instead of the current version in concep. *** Extension to defgeneric-options defgeneric-options {\bf :method-combination } The list that is cdr of the option form is stored in the generic-function object in the slot {\it method-combination\/}. Example: (:method-combination and :most-specific-last) stores {\it (and :most-specific-last)\/} in the slot {\it method-combination\/}. The body of compute-effective-method can get this information from the generic-function using the slot-accessor. *** *** Alternate version of define-method-combination*** \beginSection{Declarative Method Combination} \beginsubSection{Defining Form for Method Combination} The programmer can define new forms of method combination using the {\bf define-method-combination} macro. This allows customization of step~3 of the method combination procedure. The body of {\bf define-method-combination\/} used resembles {\bf defmacro\/} in that the body is an expression that computes a Lisp form, usually using backquote. Thus, an arbitrary combination of methods can be constructed. %The following syntax expressions need to be converted to TEX (DEFINE-METHOD-COMBINATION name [macro] ({method-group-specifier}+ ) [({method-combination-option}*)] {form}*) {method-group-specifier}:= (variable { {qualifier-pattern}+ | predicate} {keyword argument}*) {method-combination-option} :=combination-keyword value {\it name\/} is a symbol, usable as a name for this in the {\bf :method-combination} option to {\bf defgeneric-options} or {\bf defgeneric-options-setf}. By convention, non-keyword, non-{\bf nil} symbols are usually used. {\bf method-group specifiers\/} A list of method-group specifiers follows the name. Each specifier selects a subset of the applicable methods to play a particular role, either by matching their qualifiers against some patterns or by testing their qualifiers with a predicate. These method-group specifiers define all method qualifiers that can be used with this type of method combination. If an applicable method does not fall into any method-group, the system reports the error that the method is not appropriate for the kind of method-combination being used. Each method-group specifier names a variable. During the execution of the body forms, the variable is bound to a list of the methods in the method-group, in most-specific-first order. A qualifier-pattern is a list or the symbol {\bf *}. A method matches a qualifier-pattern if the method's list of qualifiers is {\bf equal} to the qualifier-pattern, except that the symbol {\bf *} in a qualifier-pattern matches anything. Thus a qualifier-pattern can be the empty list {\bf ()} (which matches primary methods, which are always unqualified), the symbol {\bf *} (which matches all methods), a true list (which matches methods with the same number of qualifiers as the length of the list, when each qualifier matches the corresponding list element), or a dotted list that ends in the symbol {\bf *} (the {\bf *} matches any number of additional qualifiers). (True lists are non-dotted lists, as defined in {\it Common Lisp: The Language\/}.) Each applicable method is tested against the qualifier-patterns and predicates in left-to-right order. As soon as a qualifier-pattern matches or a predicate returns true, the method becomes a member of the corresponding method-group and no further tests are made. Thus if a method could be a member of more than one method-group, it joins only the first such group. If a method-group has more than one qualifier-pattern, a method need only satisfy one of the qualifier-patterns to be a member of the group. The name of a predicate function can appear in place of the qualifier-patterns in a method-group specifier. The predicate is called for each method that has not been assigned to an earlier method-group, with one argument, the method's qualifier list. The predicate should return true if the method should be a member of the method-group. A predicate is distinguishable from a qualifier-pattern because it is a symbol other than {\bf nil} or {\bf *}. Method-group specifiers can have keyword options after the qualifier-patterns or predicate. Keyword options are distinguishable from additional qualifier patterns because they are not lists nor the symbol {\bf *}. The keyword options are: \def\numhangsize{60pt} \numitem{{\bf :required} {\it boolean\/}} \break If the argument is true (not {\bf nil}), and the method-group is empty (that is, no applicable methods match the qualifier-patterns or satisfy the predicate), an error is signalled. This keyword option is a convenience and does not add any expressive power. It is provided so that programmers are not tempted to omit error checking. If {\bf :required} is not specified, it defaults to {\bf nil}. The argument {\it boolean\/} is not evaluated. \numitem{{\bf :description} {\it format-string\/}} \break Programming environment tools use % TEX won't let me use #' in the next line {\bf (apply (function format) stream {\it format-string\/} (method-qualifiers {\it method\/}))} to print a concise description of a method's role (one or two words). This keyword option allows the description of a method qualifier to be defined in the same module that defines the semantic meaning of the method qualifier. In most cases {\it format-string\/} will not contain any format directives, but they are available for generality. If {\bf :description} is not specified, a default description is generated based on the variable name, the qualifier patterns, and whether this method-group includes the primary methods. The argument {\it format-string\/} is not evaluated. \def\numhangsize{25pt} Individual implementations might support other keyword options. Therefore it is required that implementations signal an error if they observe a keyword option that is not implemented locally. {\bf method-combination} options. The list of method-combination options is optional, and is distinguished from a form because it starts with a keyword. The keyword options supported are: {\bf :documentation} {\it string\/} documents the method-combination type. {\bf :around} {\it boolean\/} If the argument is true (not {\bf nil}), then the form returned by the body of define-method-combination is augmented to support :around methods. See examples below. This keyword option is a convenience and does not add any expressive power. It is provided so that programmers are not tempted to omit support for :around methods. Methods matching (:around) are extracted first from the list of applicable methods. If {\bf :around} is not specified, it defaults to {\bf nil}. The argument {\it boolean\/} is not evaluated. \def\numhangsize{25pt} Individual implementations might support other method-combination option; these must be keywords to ensure unambiguous interpretation. Therefore it is required that all implementations signal an error if they observe a keyword option that is not implemented locally. The use of method-group specifiers provides a convenient syntax for the cliched code that has to be written for every kind of method combination, to select methods, divide them among the possible roles, and perform the necessary error checking. It is possible to perform further filtering of methods in the body forms, using normal list-processing operations and the functions {\bf method-qualifiers} and {\bf invalid-method-error}. It is permissible to {\bf setq} the variables named in the method-group specifiers and to bind additional variables. It is also possible to bypass the method-group specifier mechanism and do everything in the body forms. This is accomplished by writing a single method group with {\bf *} as its only qualifier-pattern; the variable is then bound to a list of all of the applicable methods, in most-specific-first order. The body {\it forms\/} compute and return the Lisp form that specifies how the methods are combined, that is, the effective method. The body of {\bf define-method-combination} resembles the body of {\bf defmacro} and uses backquote in a similar way. The function {\bf make-method-call} must be used in constructing the Lisp form; it hides the implementation-dependent details of how methods are called. Programmers always use {\bf make-method-call} to translate from the lists of method objects produced by the method-group specifiers to Lisp forms that invoke those methods. Erroneous conditions detected by the body should be reported with {\bf method-combination-error} or {\bf invalid-method-error}; these functions add any necessary contextual information to the error message and will use the condition signalling system when and if it is adopted into Common Lisp. The body {\it forms\/} are evaluated inside of the bindings of the compute-effective-method lambda-list and method-group specifiers. The variable {\it generic-function\/} is available in the body forms of the combination definition. Since there are no declarations except inside a user form, declarations cannot effect bindings of variables in the lambda-list (e.g {\it generic-function\/} or any method-group variables. The code may use any information obtainable from the particular generic-function object. The functions {\bf make-method-call}, {\bf method-combination-error}, and {\bf invalid-method-error} can be called from the body {\it forms\/}, or from functions called by the body {\it forms\/}. The action of these three functions can depend on dynamic variables bound by the object system before calling the method-combination function. These variables might contain the parameter list of the effective method or other implementation-dependent information. \endsubSection%{Defining Form for Method Combination} \beginsubSection{Examples of define-method-combination} %These examples could be put in the EXAMPLES field of the DEFINE-METHOD-COMBINATION %function description. I think it's better to put them into the Concepts %chapter and cross-reference them from the function description. \screen! ;The default method-combination, the hard way (define-method-combination standard ((around (:around)) (before (:before)) (primary ()) (after (:after))) (unless primary (method-combination-error "A primary method is required.")) (make-method-call `(,@around (multiple-value-prog2 ,(make-method-call before) ,(make-method-call primary :call-next-method t) ,(make-method-call (reverse after)))) :call-next-method t)) ;The default method-combination using keyword options (define-method-combination standard ((before (:before)) (primary () :required t) (after (:after))) (:around t) (multiple-value-prog2 ,(make-method-call before) ,(make-method-call primary :call-next-method t) ,(make-method-call (reverse after)))) ;A simple way to try several methods until one returns non-nil (define-method-combination and ((methods () (:and))) (make-method-call methods :operator 'and)) ;A more complete version of the preceding, adding around methods and checking that there is a primary method. (define-method-combination and ((primary () (:and) :required t)) (:around t :description "First method returning non-NIL")) (make-method-call primary :operator 'and :identity-with-one-argument t)) ;Order methods by positive integer qualifiers (define-method-combination example-method-combination ((methods positive-integer-qualifier-p)) (:around t) (make-method-call (stable-sort methods #'< :key #'(lambda (method) (first (method-qualifiers method)))))) (defun positive-integer-qualifier-p (method-qualifiers) (and (= (list-length method-qualifiers) 1) (typep (first method-qualifiers) '(integer 0 *)))) \label Using Parameter Passing ;Using method-combination parameters, ;one can obtain parametric ordering for {\it and\/} combination. (define-method-combination and ((primary () (:and) :required t)) (:around t)) (when (apply order-parameter (cdr (method-combination generic-function))) (setq primary (reverse primary))) (make-method-call primary :operator 'and :identity-with-one-argument t)) (defun order-parameter (&optional (order :most-specific-first)) (case order (:most-specific-first ()) (:most-specific-last t) (otherwise (method-combination-error ''~S is an invalid order.~@ :most-specific-first and :most-specific-last are the possible values.'' order))) \endscreen! \endsubSection%{Examples of define-method-combination} \endSection%{Declarative Method Combination} *** End Declarative Method combination***  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 20 Jan 87 13:18:23 EST Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 20 Jan 87 10:10:03 PST Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 40834; Tue 20-Jan-87 10:43:48 EST Date: Tue, 20 Jan 87 10:42 EST From: Daniel L. Weinreb Subject: change-class and class redefinition To: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870119235610.0.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <870120104211.2.DLW@CHICOPEE.SCRC.Symbolics.COM> Date: Mon, 19 Jan 87 23:56 EST From: David A. Moon [CLASS-CHANGED was the best name I could think of off-hand. In Flavors this is named TRANSFORM-INSTANCE. In CommonLoops it is named CHANGE-CLASS-INTERNAL, I believe.] CLASS-CHANGED is a good name. This name makes it clear that you aren't supposed to call this function yourself; you're only supposed to handle it. (I wish there were a term for that kind of generic function.) The other two names are both imperative, and so don't make it clear. You have to specify what sort of method combination is used for CHANGE-CLASS. Presumably the default one, but it should be specified in case there's any question. (5) Restrictions on when CHANGE-CLASS can be called Redefining a class modifies the existing class object to reflect the new class definition; it never creates a new class object for the class. All methods applicable to the class remain, except for methods created by the :accessor, :reader, :accessor-prefix, and :reader-prefix options when those options have been changed in the DEFCLASS form. Do accessors that used to be defined, but are not now defined, actually get undefined (fmakunbound'ed)?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 20 Jan 87 00:51:06 EST Received: from [192.10.41.234] by SAIL.STANFORD.EDU with TCP; 19 Jan 87 21:42:16 PST Received: from EUPHRATES.SCRC.Symbolics.COM by MEAD.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 44265; Mon 19-Jan-87 23:56:22 EST Date: Mon, 19 Jan 87 23:56 EST From: David A. Moon Subject: change-class and class redefinition To: Common-Lisp-Object-System@SAIL.STANFORD.EDU References: <861020222040.5.MOON@EUPHRATES.SCRC.Symbolics.COM>, <861021103246.4.GREGOR@AVALON.isl.parc.xerox.com>, <861117153938.3.GREGOR@AVALON.isl.parc.xerox.com>, <861212100117.4.SKEENE@JUNCO.SCRC.Symbolics.COM>, <861217234009.5.MOON@EUPHRATES.SCRC.Symbolics.COM>, <861228213807.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <870119235610.0.MOON@EUPHRATES.SCRC.Symbolics.COM> Here's what I have so far on the subject, culled from the referenced messages plus my own head. This is unfinished, but it seems worth putting it out for comments in its current condition. This message won't get out of the building until the snow stops, but I can hope that it will get to SU-AI sometime Tuesday morning. Class changing writeup First we will discuss CHANGE-CLASS. What happens when DEFCLASS redefines a class is discussed later. Changes to the change-class writeup: In the arguments field, it isn't really true that instance can be any object. The arguments field should allude to the restriction discussed in the remarks field. Gregor's example of converting between rectangular and polar coordinates, mailed out 17 Nov 86, could be inserted into the examples field. All other fields are okay except the remarks field. Replace it according to the following: (1) Not all objects can change their class If C1 and C2 are classes that were defined by DEFCLASS, without using the :METACLASS option in either case, and X is an instance of class C1, X's class can be changed to C2. This is the only case for which this standard guarantees that CHANGE-CLASS is allowed. Both before and after the call to CHANGE-CLASS, X's metaclass is the default metaclass. Whether CHANGE-CLASS is allowed for instances of a different metaclass than the default one is up to the implementor of the particular metaclass. The Metaclass Protocol document will describe how to control this. Implementations can choose to support CHANGE-CLASS in additional cases if they desire. For example, this standard does not require CHANGE-CLASS to or from a standard-type-class to be supported, however it is valid for an implementation to support it for some standard-type-classes. In any case where CHANGE-CLASS is not allowed, it signals an error. (2) Changing the metaclass Whether CHANGE-CLASS is allowed to change an object's metaclass is up to the implementors of the two particular metaclasses. The Metaclass Protocol document will describe how to control this. (3) Preservation of slot values CHANGE-CLASS preserves the values of slots that are common between the old and new classes, and initializes any remaining slots of the new class. Specifically, for each :ALLOCATION :INSTANCE slot of the new class, if there is a slot by the same name in the old class (with any :ALLOCATION other than :NONE), the slot's value is preserved. This means that if the slot has a value, the value returned by SLOT-VALUE after the CHANGE-CLASS is EQL to the value returned by SLOT-VALUE before the CHANGE-CLASS, while if the slot is uninitialized, it remains uninitialized and no error is signalled. Each :ALLOCATION :INSTANCE slot of the new class with no slot by the same name in the old class is initialized to the value of its :INITFORM, or remains uninitialized if there is no :INITFORM. This is the same as the initialization done by MAKE-INSTANCE, except that no initialization methods are invoked and no MAKE-INSTANCE initialization arguments are present. The value of each :ALLOCATION :INSTANCE slot of the old class with no slot by the same name in the new class is discarded. (4) CLASS-CHANGED methods [CLASS-CHANGED was the best name I could think of off-hand. In Flavors this is named TRANSFORM-INSTANCE. In CommonLoops it is named CHANGE-CLASS-INTERNAL, I believe.] After completing all other actions, CHANGE-CLASS invokes the generic function CLASS-CHANGED on two arguments, named previous and current, representing two views of the instance. The returned value is ignored. The default method for CLASS-CHANGED does nothing, but programmers can define their own methods to do such things as initialize new slots differently from MAKE-INSTANCE or copy information from slots that only exist in the old class into differently-named slots in the new class. The first argument, previous, is an instance of the old class created to hold the old slot values temporarily. It has dynamic extent, thus it is an error to reference previous in any way after CLASS-CHANGED returns. The typical use of previous is as an argument for SLOT-VALUE, WITH-SLOTS, or an accessor generic function, to extract old slot values. In fact any function, generic or not, can receive previous as an argument; thus information about previous that is not directly stored in slots can be extracted. The second argument, current, is the instance given as the first argument to CHANGE-CLASS. At the time CLASS-CHANGED is called it has been fully converted to the new class. CLASS-CHANGED methods can, of course, make the slot value preservation behavior of CHANGE-CLASS different from that described earlier. (5) Restrictions on when CHANGE-CLASS can be called [this section needs work] There are two semantic difficulties associated with CHANGE-CLASS. The first problem occurs if an object's class is changed while a generic function is executing with that object as an argument. If the object's class is used for method selection, the currently executing method might now be the wrong method, not applicable to the object's new class. No known \CLOS\ implementation can undo the effects of executing the wrong method and cause the right method to be executed instead, so the wrong method simply continues executing. When a particular generic function invocation invokes multiple methods because of method combination or CALL-NEXT-METHOD, an implementation is permitted, but not required, to decide on the set of methods to be invoked at the beginning of the generic function invocation. Thus the set of methods invoked after the class has been changed is implementation-dependent and not defined by this standard. The second problem concerns optimization of slot access. This standard permits, but does not require, an implementation to compile WITH-SLOTS in an early-binding style. [Does this apply to explicit calls to SLOT-VALUE inside methods also?] This means that the determination of how slots are to be accessed (their memory address and whether a method needs to be invoked) can be done when the actual slot access occurs, when the WITH-SLOTS is entered, when the method containing the WITH-SLOTS is entered, or when the generic function that invokes the method is called. This implementation freedom is a concession to efficiency, which is judged more important than the semantics of CHANGE-CLASS. If the class is changed after the determination of how slots are to be accessed and before the actual slot access, the results are undefined. This means that if a method changes the class of an argument, that method, and any other methods invoked by the same generic function invocation, must not access slots of that argument afterwards. [Another way to explain this is to speak of an activation record corresponding to the lexical context in which the class of an object is known (e.g. because of a parameter specializer or because of a method discrimination), and to say that changing the class of the object puts the activation record into "a wierd state".] Note that the call to CHANGE-CLASS that causes semantic difficulties might not be lexically visible. CHANGE-CLASS could be called by a function that is called by a method. All that matters is that the class is changed while the method is dynamically active. Note that in multi-process systems, the semantic difficulties discussed above occur even when the generic function invocation is in one process and CHANGE-CLASS is called in a different process. [The following comes from Flavors. I believe all implementations should be able to support this, but if some implementation has great difficulty implementing this we could relax the standard.] The second semantic difficulty occurs when CHANGE-CLASS changes the arrangement in storage of the slots. By special dispensation, this difficulty never occurs for the implicit call to CHANGE-CLASS that occurs when a class is redefined. In addition, the programmer can avoid this difficulty by obeying the following rules: If the old and new classes have the same slots, and inherit them from the same superclasses, then their arrangement in storage will be the same. This can be accomplished by using mixin classes that do not define any instance variables of their own, and using CHANGE-CLASS only to change which of these mixins are included. A more complex solution ensures only that the slots that are actually accessed remain in the same arrangement in storage. These slots must be inherited from common superclasses. The old and new classes can have additional slots supplied by superclasses earlier in the precedence list than them. [This is not explained very well, the idea is that slot allocation is from the least-specific-class first, i.e. in reverse order of precedence, so if only slots in the common tail of the class precedence list are accessed, it's guaranteed that those slots won't have changed their arrangement in storage.] =============== Next we discuss what happens when DEFCLASS redefines a class in a way that changes the set of slots in an instance, or their order in storage. Note that the affected class might not be the one whose DEFCLASS was re-evaluated; it could be a subclass of that class. [Part of the remarks field of DEFCLASS will be replaced by this.] Redefining a class modifies the existing class object to reflect the new class definition; it never creates a new class object for the class. All methods applicable to the class remain, except for methods created by the :accessor, :reader, :accessor-prefix, and :reader-prefix options when those options have been changed in the DEFCLASS form. Redefining a class in a way that changes the set of slots in an instance, or their order in storage, also creates an [italics] obsolete class object. This class has no name. The only instances of this class that can ever exist are those created as the [italics] previous argument to a CLASS-CHANGED method. All methods applicable to the class before redefinition, including methods created by the :accessor, :reader, :accessor-prefix, and :reader-prefix options, become applicable to the obsolete class also. This allows a CLASS-CHANGED method to extract information from its [italics] previous argument. [Are future changes in methods reflected to the obsolete class? Deal with additions, deletions, and redefinitions separately? Should the standard define this?] When an instance of a class that has been redefined is accessed, the instance is automatically updated to the new class definition. "Accessed" means calling a generic function with the instance as an argument that is used for method selection, calling one of the functions CLASS-OF, SLOT-VALUE, TYPE-OF, TYPEP [maybe others?]. Updating an instance does not change its identity as defined by the EQ function; it changes the class and slots of that particular instance; it does not create a new instance. Whether updating an instance consumes storage is implementation-dependent. Updating an instance calls CHANGE-CLASS, whose behavior and programmability using CLASS-CHANGED methods was described earlier. [Still to be defined: how if you redefine a class several times, you can create CLASS-CHANGED methods that perform updates from one particular version of the class to another particular version. The simplest answer is that you can't, instead you have to write your methods to work for any version of the class.] [What about addition/removal of class variables?]  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 19 Jan 87 21:37:44 EST Received: from Cabernet.ms by ArpaGateway.ms ; 19 JAN 87 16:24:14 PST Date: 19 Jan 87 16:23 PST From: Gregor.pa@Xerox.COM Subject: Re: New version of PCL for Genera In-reply-to: franz!ficl!jkf@ucbarpa.Berkeley.EDU (John Foderaro)'s message of Mon, 19 Jan 87 15:28:50 PST To: franz!ficl!jkf@ucbarpa.Berkeley.EDU cc: CommonLoops.pa@Xerox.COM Message-ID: <870119-162414-1108@Xerox> Oops, I forgot to bump *pcl-system-date* when I copied the files to parcvax. Please edit *pcl-system-date* (in defsys) to be "1/19/87" or ftp a new version of defsys. Thanks Gregor  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 19 Jan 87 19:07:09 EST Received: from Cabernet.ms by ArpaGateway.ms ; 19 JAN 87 15:54:08 PST Return-Path: Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 19 JAN 87 15:52:43 PST Received: by ingres.Berkeley.EDU (5.57/1.14) id AA06508; Mon, 19 Jan 87 15:51:45 PST Date: Mon, 19 Jan 87 15:51:45 PST From: dcmartin@ingres.berkeley.edu (David C. Martin) Message-Id: <8701192351.AA06508@ingres.Berkeley.EDU> To: commonloops.pa@Xerox.COM Subject: YABIPCL (Yet Another Bug In PCL) ExCL version 1.5.vax.2 PCL version 11/11 (ndefstruct (foo (:class class) (:conc-name nil) (:include new-object)) (data (make-string 512 :initial-element '#\space) :type string :allocation :class) (barf 10 :type fixnum)) FOO (setq f (make-foo)) #S(FOO BARF 10) (ppi f) FOO CLASS CLASS VARIABLES: DATA (MAKE-STRING ...) INSTANCE VARIABLES: BARF 10 How come the class variable was never evaluated? dcm  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 19 Jan 87 19:07:01 EST Received: from Cabernet.ms by ArpaGateway.ms ; 19 JAN 87 14:35:33 PST Date: 19 Jan 87 14:34 PST From: Gregor.pa@Xerox.COM Subject: Re: Bug(?) in defmeth and number of arguments In-reply-to: Frank Halasz 's message of Thu, 15 Jan 87 16:04:59 CST To: halasz@MCC.COM cc: CommonLoops.pa@Xerox.COM Message-ID: <870119-143533-172@Xerox> Date: Thu, 15 Jan 87 16:04:59 CST From: Frank Halasz It appears that you cannot have methods with the same name but different numbers of arguments. For example, CommonLoops will not work with the following defmeths. That's right. All methods must have the same number of required arguments.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 19 Jan 87 19:06:54 EST Received: from Cabernet.ms by ArpaGateway.ms ; 19 JAN 87 14:32:51 PST Date: 19 Jan 87 14:31 PST From: Gregor.pa@Xerox.COM Subject: Re: bug in pcl 11/11 under ExCL 1.{3,4} In-reply-to: dcmartin@ingres.berkeley.edu (David C. Martin)'s message of Sun, 18 Jan 87 11:45:26 PST To: dcmartin@ingres.berkeley.edu cc: commonloops.pa@Xerox.COM Message-ID: <870119-143251-171@Xerox> Try the following example instead. (defun foo (x) 'default) (make-specializeable 'foo) (defclass foo () ((data :inhtform nil :accessor foo))) (foo (make-array 10)) What happens?? If you get an error, please send me a backtrace. Also, how is it that your version of make-specializable works?? I just found a bug (which I see was previously reported) which I would have though would keep make-specializable from working. Also, it was our intention that none of the functions in the silver book were specializable unless the "manufacturer" explicitly said they were.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 19 Jan 87 17:23:06 EST Received: from Cabernet.ms by ArpaGateway.ms ; 19 JAN 87 13:13:21 PST Date: 19 Jan 87 13:12 PST From: Gregor.pa@Xerox.COM Subject: New version of PCL for Genera To: CommonLoops.pa@Xerox.COM cc: Gregor.pa@Xerox.COM Message-ID: <870119-131321-1596@Xerox> There is a new version of PCL on parcvax.xerox.com. This version runs in Symbolics Releease 7.0 (Genera). It does not work in Franz 1.4 yet, but I am working on that, I don't know about the others yet. NOTE: after you get the files, read 3600-notes.txt, in order to use this version of PCL you must load the file rel-7-patches first.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 18 Jan 87 16:13:14 EST Received: from Cabernet.ms by ArpaGateway.ms ; 18 JAN 87 11:47:45 PST Return-Path: Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 18 JAN 87 11:46:59 PST Received: by ingres.Berkeley.EDU (5.57/1.14) id AA14493; Sun, 18 Jan 87 11:45:26 PST Date: Sun, 18 Jan 87 11:45:26 PST From: dcmartin@ingres.berkeley.edu (David C. Martin) Message-Id: <8701181945.AA14493@ingres.Berkeley.EDU> To: commonloops.pa@Xerox.COM Subject: bug in pcl 11/11 under ExCL 1.{3,4} Extended Common Lisp 1.4 (1/14/87 14:25) Copyright (c) 1986, Franz Inc., Alameda, Ca (use-package 'pcl) T (pcl::make-specializable 'length) # (ndefstruct (text-line (:class class) (:conc-name nil)) (data nil :type array) (offset 0 :type fixnum) (length 0 :type fixnum)) TEXT-LINE (make-array 10) #(Error: Attempt to do an array operation on 61667360 which is not an array. [1] This is really wierd 'cause if I change the length slot to be named ``size'' then the error goes away. dcm  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 16 Jan 87 15:52:07 EST Received: from Cabernet.ms by ArpaGateway.ms ; 16 JAN 87 11:30:15 PST Date: 16 Jan 87 11:29 PST From: Gregor.pa@Xerox.COM Subject: Re: --- In-reply-to: ehl%cogsci.Berkeley.EDU@berkeley.edu (Edward H. Lay)'s message of Fri, 9 Jan 87 19:07:47 PST To: ehl%cogsci.Berkeley.EDU@berkeley.edu cc: DMACLAUGHLIN@bbng.arpa, commonloops.pa@Xerox.COM Message-ID: <870116-113015-2374@Xerox> ...other stuff... 4) I ran into a problem with the default printing method. It seems that this method performs a funcall on the slot accessor for each slot The problem isn't withthe printing method it's with the default all-slots method. ed lay Right, this is fixed in the newest version.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 16 Jan 87 15:51:52 EST Received: from Cabernet.ms by ArpaGateway.ms ; 16 JAN 87 11:28:47 PST Date: 16 Jan 87 11:26 PST From: Gregor.pa@Xerox.COM Subject: Re: specializing macros In-reply-to: dcmartin@ingres.berkeley.edu (David C. Martin)'s message of Fri, 9 Jan 87 14:06:11 PST To: dcmartin@ingres.berkeley.edu cc: commonloops.pa@Xerox.COM Message-ID: <870116-112847-2372@Xerox> Date: Fri, 9 Jan 87 14:06:11 PST From: dcmartin@ingres.berkeley.edu (David C. Martin) There is a macro called ``time'' in the lisp package of ExCL. When I attempt to specialize this macro w/ make-specializable it barfs since there is no funcallable object for ``time''. My quick workaround was to shadow the function time, but this seems sort of foolish as make-specializable should be able to handle this situation. Comments? You can't specialize a macro. What would it mean? When would the method lookup happen?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 16 Jan 87 11:28:40 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Jan 87 08:21:05 PST Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 45087; Fri 16-Jan-87 11:19:34 EST Date: Fri, 16 Jan 87 11:18 EST From: Sonya E. Keene Subject: new versions of files To: lgd@stanford.sail.edu, rpg@stanford.sail.edu cc: common-lisp-object-system@sail.stanford.edu Message-ID: <870116111824.2.SKEENE@JUNCO.SCRC.Symbolics.COM> I wrote new versions of concepts and functions. Functions.tex: Edited the method combination functions. Edited the :method-combination options to defgeneric-options, defgeneric-options-setf, and make-generic-function. Edited the defclass :initform option to talk about when it is evaluated, according to the mail about it. Concepts.tex: Put in a new Inheritance chapter that talks about inheritance of slots, methods (slightly), and defclass options. I included Larry Masinter's comments. Terminology changes in both files: Changed occurrences of "daemon" method combination type to "standard". Changed occurrences of "unqualified method" to "primary method" where it was appropriate. I think that's all I did. I'll hand control of these files back to you two now. I'm going to work on updating the Glossary to use the new terminology.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 16 Jan 87 10:55:28 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 16 Jan 87 07:48:32 PST Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 45061; Fri 16-Jan-87 10:44:52 EST Date: Fri, 16 Jan 87 10:44 EST From: Sonya E. Keene Subject: Re: draft on inheritance of slots and defclass options To: Masinter.pa@Xerox.COM cc: skeene@STONY-BROOK.SCRC.Symbolics.COM, common-lisp-object-system@sail.stanford.edu In-Reply-To: <870115-155717-1583@Xerox> Message-ID: <870116104441.0.SKEENE@JUNCO.SCRC.Symbolics.COM> Line-fold: No Date: 15 Jan 87 16:00 PST From: Masinter.pa@Xerox.COM Thanks for replying so quickly. This morning I made most of the changes you suggested, and will write out the concepts file today. I liked the phrasing "In general, xs are inherited by subclasses; that is, ..." You used it "Methods are inherited by subclasses. That is, a method provided by a class is applicable ..." I'd like it INHERITANCE OF SLOTS In general, slots are inherited by subclasses. That is, slots defined in a class are usually also slots in any subclass of that class. The inheritance of slots depends on .... I made this wording change. - - - - - - - - I was confused by the organization of defclass options because the initial set of options were really slot options within a defclass rather than defclass options. Right, I forgot to put in a subheading called "Inheritance of DEFCLASS Slot-options". That header makes the organization much clearer. The subsection "Inheritance of DEFCLASS Options" is divided into two pieces: one for the slot-options and one for the class-options. I see no advantage in spelling out :READER -- ... ;see :ACCESSOR instead of saying :ACCESSOR, :READER -- These options are not inherited; that is, subclasses do not ... I could do it that way, but I prefer to list each option separately. If the reader-person wanted to find out how the :READER option was inherited, it's easier to find it if each option is separated out from the text. Also, the way I did it, I can refer to the :ACCESSOR slot-option in the text for the :READER-PREFIX and :ACCESSOR-PREFIX class-options, rather than repeating that paragraph again in the class-options part. ----- Your section says EXAMPLES OF INHERITANCE yet it is a single example. Rather than packing them all into a single example, it would be much clearer to give separate examples. You could call it a single example, but it illustrates many of the inheritance concepts. One advantage of the way its done now is brevity (not usually my strong point as a writer), so I hesitate to make this section even longer. But I'll play around with separating each concept into its own example and see if that works better.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 15 Jan 87 20:21:35 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jan 87 17:13:39 PST Received: from Cabernet.ms by ArpaGateway.ms ; 15 JAN 87 15:57:17 PST Date: 15 Jan 87 16:00 PST From: Masinter.pa@Xerox.COM Subject: Re: draft on inheritance of slots and defclass options In-reply-to: Sonya E. Keene 's message of Thu, 15 Jan 87 11:31 EST To: skeene@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@sail.stanford.edu Message-ID: <870115-155717-1583@Xerox> I liked the phrasing "In general, xs are inherited by subclasses; that is, ..." You used it "Methods are inherited by subclasses. That is, a method provided by a class is applicable ..." I'd like it INHERITANCE OF SLOTS In general, slots are inherited by subclasses. That is, slots defined in a class are usually also slots in any subclass of that class. The inheritance of slots depends on .... - - - - - - - - I was confused by the organization of defclass options because the initial set of options were really slot options within a defclass rather than defclass options. I see no advantage in spelling out :READER -- ... ;see :ACCESSOR instead of saying :ACCESSOR, :READER -- These options are not inherited; that is, subclasses do not ... ----- Your section says EXAMPLES OF INHERITANCE yet it is a single example. Rather than packing them all into a single example, it would be much clearer to give separate examples.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 15 Jan 87 18:23:17 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jan 87 15:11:28 PST Received: from Cabernet.ms by ArpaGateway.ms ; 15 JAN 87 14:03:16 PST Date: 15 Jan 87 13:05 PST From: Gregor.pa@Xerox.COM Subject: Re: Issues for the CLOS committee to start focussing on In-reply-to: Danny Bobrow 's message of 11 Jan 87 22:22 PST To: Bobrow.pa@Xerox.COM cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870115-140316-1301@Xerox> Date: 11 Jan 87 22:22 PST From: Danny Bobrow The name for standard method combination in the concepts document, and elsewhere No, it should be some word which includes default, maybe even just default. This is to be consistent with default-class, default-method etc.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 15 Jan 87 18:19:39 EST Received: from Cabernet.ms by ArpaGateway.ms ; 15 JAN 87 14:17:33 PST Return-Path: <@MCC.COM:halasz@mcc.com> Received: from MCC.COM by Xerox.COM ; 15 JAN 87 14:05:36 PST Received: from milano.sw.mcc.com by MCC.COM with TCP; Thu 15 Jan 87 16:05:21-CST Received: from geza (geza.ARPA) by milano.sw.mcc.com (4.12/STP) id AA13710; Thu, 15 Jan 87 16:05:23 cst Date: Thu, 15 Jan 87 16:04:59 CST From: Frank Halasz Posted-Date: Thu, 15 Jan 87 16:04:59 CST Message-Id: <8701152204.AA07191@geza> Received: by geza (1.1/STP) id AA07191; Thu, 15 Jan 87 16:04:59 CST Newsgroups: fa.commonloops Subject: Bug(?) in defmeth and number of arguments Expires: References: Sender: Reply-To: halasz%geza.UUCP@seismo.css.gov () Followup-To: Distribution: stp Organization: MCC, Austin, Texas Keywords: To: CommonLoops.pa@Xerox.COM It appears that you cannot have methods with the same name but different numbers of arguments. For example, CommonLoops will not work with the following defmeths. (defmeth move ((self window) (x integer) (y integer)) ... (defmeth move ((self window) (pos position)) It doesn't work with the followwing defmeths either (in case you thought it had something to do with common first arg type) (defmeth move ((self window) (x integer) (y integer)) ... (defmeth move ((self 3d-window) (x integer) (y integer) (z integer)) ... What PCL does is it uses only methods with the same number of args as the method with the minimum number of args defined so far. All other methods are ignored. So, if you define a 3 arg method, the method will work until you define a 1 or 2 arg method. When the 1 or 2 arg methods are defined, the 3 or more arg methods no longer work. If you define a 2 arg method first, the 3 or more arg methods are never accessable. Below are examples. These are from PCL on top of EXCL, but it works the same in LUCID. (PCL from 12.02). geza% excl Extended Common Lisp 1.3 (11/17/86 14:48) (c) copyright 1986, Franz Inc., Alameda, Ca halasz #1: (defmeth test ((self integer)(arg1 integer)) "two args" "two args") TEST halasz #2: (test 1 1) "two args" halasz #3: (defmeth test ((self symbol)) "one arg" "one arg") TEST halasz #4: (test 1 1) Error: No matching method for: TEST. [1] halasz #5: :pop halasz #6: (test 'A) "one arg" halasz #7: (test 'A 'A) Continuable Error: EXCL::ANONYMOUS-LAMBDA got 2 args, wanted at most 1. If continued with :continue, Ignore the extra args. [1c] halasz #8: :pop halasz #9: (defmeth test ((self integer)) "one arg 2" "one arg 2") TEST halasz #10: (test 1) "one arg 2" halasz #11: (test 1 1) Continuable Error: EXCL::ANONYMOUS-LAMBDA got 2 args, wanted at most 1. If continued with :continue, Ignore the extra args. [1c] halasz #12: :pop halasz #13: (defmeth test ((self list )(arg1 list))"one arg 3" "one arg 3") TEST halasz #14: (test (LIST 1)(LIST 3)) Error: No matching method for: TEST. -- Frank -- ------------------------------------------------------------ Frank Halasz MCC Software Technology 9390 Research Blvd Austin TX 78759. [512]338-3648 halasz@MCC.COM or {harvard,ihnp4,nike,seismo}!ut-sally!im4u!milano!halasz  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 15 Jan 87 11:45:14 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 15 Jan 87 08:33:06 PST Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 44527; Thu 15-Jan-87 11:31:35 EST Date: Thu, 15 Jan 87 11:31 EST From: Sonya E. Keene Subject: draft on inheritance of slots and defclass options To: common-lisp-object-system@sail.stanford.edu Message-ID: <870115113125.4.SKEENE@JUNCO.SCRC.Symbolics.COM> Most of the following came from Danny's message of awhile back. We changed the inheritance behavior of :type so that the compiler could do some optimization based on the :type option given in a local DEFCLASS description. This draft seems long for the subject matter it's covering, but I think it's worth spelling out all the possibilities. As soon as people read this and give comments about it, I'll edit it into the document. ------------------------------------------------ INHERITANCE A class inherits methods, slots, and some DEFCLASS options from all of its superclasses. However, the class can choose to override an inherited method, slot, or DEFCLASS option. This section describes what is inherited from superclasses, and how a class can override an aspect of inherited behavior. INHERITANCE OF METHODS Methods are inherited by subclasses. That is, a method provided by a class is applicable for use on instances of any subclass of that class. In some cases, an inherited method can be shadowed by providing a method for a more specific class. When standard method combination is used, the primary method can be shadowed by a method on a more specific class. (However, if the more specific method uses CALL-NEXT-METHOD, the next most specific primary method is called.) The inheritance of methods acts the same way regardless of whether the method was created using DEFMETHOD or by using one of the DEFCLASS options that cause methods to be generated automatically (for reading or accessing the value of a slot). INHERITANCE OF SLOTS In general, slots are inherited by subclasses. An instance has at most one slot by any given name accessible to it. The inheritance of slots depends on whether the inherited slot is allocated by :class or :instance, and whether the :allocation slot option is given in the local slot-description. There are several different cases. 1. In the simplest case, a class does not provide a local description of a slot with the same name as a slot provided by its superclass. If it is an :instance slot, the subclass allocates storage for it in each instance. If it is a :class slot, the allocation of the slot is done by the superclass, and that single slot is accessible by instances of both the superclass and the subclass. 2. Whenever a class specifies :allocation :class, a new :class slot is created, and any slot with that name provided by a superclass is not accessible to instances of this class. 3. Whenever a class specifies :allocation :none for a slot, no slot with that name is accessible to instances of this class. Thus, the :allocation :none option allows for subtractive inheritance; a class can specify :allocation :none to prevent access to a slot supplied by a superclass. 4. Whenever a class provides a local description of an :instance slot, and its superclass provides a description of a :class slot with the same name, only the :instance slot that was described locally is accessible to the subclass. Only the :class slot is accessible instances of the superclass. (Note that the DEFCLASS default :allocation is :instance, so a slot description is treated as an :instance slot if the :allocation option is not explicitly supplied.) 5. Whenever a class provides a local description of an :instance slot, and its superclass also provided a description of an :instance slot with the same name, the effect of the local slot description is to override or alter some of the inherited characteristics of the slot, such as its :initform or :type options. (The inheritance behavior of each DEFCLASS option is described further on in this section.) The wording of the above cases mentions one subclass and one superclass, but a class often has more than one superclass. The class precedence order is used to determine how the slots are inherited. When a class is defined, the slots that it will be able to access are determined by considering each local slot-description, and the description of each slot that is given by the most specific superclass in the class precedence list. The examples further on in this section should clarify this behavior. INHERITANCE OF DEFCLASS OPTIONS :ACCESSOR -- This option is not inherited; subclasses do not automatically generate methods for accessing a slot unless the :ACCESSOR prefix is specified in the local description. However, a subclass does inherit the methods generated by this option, in the sense that the methods are applicable for instances of the subclass. Because these methods are primary methods, when standard method combination is used the subclass can shadow the inherited methods by providing more specific methods, either by using the :ACCESSOR option or using DEFMETHOD. The type of inheritance described here also applies to the methods generated by the :reader, :accessor-prefix, and :reader-prefix options. :READER -- This slot option is not inherited; see the description of the :accessor slot-option. :ALLOCATION -- This option is not inherited by subclasses. However, if a local slot description is given for a slot with the same name as a slot provided by a superclass, this option affects the inheritance of the slot. The semantics of slot inheritance and the :allocation option are described above. :INITFORM -- The :initform option is inherited, and can be overridden in a straightforward way. In the case of an inherited :instance slot, if the :initform option is given in a local description, the local :initform completely overrides the inherited :initform. :TYPE -- The :TYPE option is inherited as follows. When a class is being defined, the slot descriptions of all of its superclasses (including itself) are considered, regardless of the allocation of the slot. The type of the value of the slot is constrained to satisfy all of the type constraints given in the descriptions of each of its superclasses, including itself. That is, if T1, T2 and so on are the type constraints given by the class and all of its superclasses, the value of the slot must satisfy (typep value '(and T1 T2 T3...). [This inheritance behavior allows a compiler to optimize on the basis of the :TYPE option in the DEFCLASS form. Some operations can be improved, when the slot directly is involved in an arithmetic expression, such as being able to emit the machine addition instruction with only overflow checking.] CLASS OPTIONS: :ACCESSOR-PREFIX -- This slot option is not inherited; see the description of the :ACCESSOR slot-option. :READER-PREFIX -- This slot option is not inherited; see the description of the :ACCESSOR slot-option. :CONSTRUCTOR -- This option has no effect on subclasses; it is not inherited. :DOCUMENTATION -- This option has no effect on subclasses; it is not inherited. :METACLASS -- This option has no effect on subclasses; it is not inherited. EXAMPLES OF INHERITANCE: (defclass C1 () ((S1 :initform 5.4 :type number) (S2 :allocation :class)) (defclass C2 (C1) ((S1 :initform 5 :type integer) (S2 :allocation :instance) (S3 :accessor C2-S3)) :reader-prefix C2-) (defclass C3 (C2) ((S2 :allocation :none))) (defclass C4 (C3 C2) ()) C1 has an :instance slot named S1, whose default initial value is 5.4, and whose value is constrained to be a number. C1 also has a :class slot named S2. C2 has access to an :instance slot named S1, whose default initial value is 5, and whose value is constrained to satisfy (typep value '(AND integer number)). C2 has access to two :instance slots, named S1 and S2. C2 has methods defined for reading the value of its slots; these methods are for the generic functions named: C2-S1, C2-S2, and C2-S3. There is also a SETF method for use with C2-S3. C3 has access to an :instance slot named S1, whose default initial value is 5, and whose value is constrained to satisfy (typep value '(AND integer number)). C3 also has access to a slot named S3. C3 has methods applicable for reading the value of the slots S1, S2, and S3. Note that although C3 has a method for reading the value of slot S2, it does not have access to that slot, so using the method would result in an error. The class precedence order for C4 is: (C4 C3 C2 C1). Because C3 comes before C2 in the precedence order, class C4 does not have access to slot S2.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 14 Jan 87 18:50:05 EST Received: from Semillon.ms by ArpaGateway.ms ; 14 JAN 87 11:55:44 PST Return-Path: <@CONGER.bbn.com:dmaclaug@BBNJ.ARPA> Received: from CONGER.bbn.com ([128.89.0.35]) by Xerox.COM ; 14 JAN 87 11:53:16 PST Received: from COD.bbn.com by CONGER.bbn.com via CHAOS with CHAOS-MAIL id 12164; Wed 14-Jan-87 14:50:23-EST Date: Wed, 14 Jan 87 14:51 EST From: Dawn MacLaughlin Subject: Problem using make-specializable To: commonloops.pa@Xerox.COM cc: dmaclaughlin@J.BBN.COM, kanderson@J.BBN.COM Message-ID: <870114145105.1.DMACLAUGHLIN@COD.bbn.com> In Symbolics 3670 Release 6.G2, IP-TCP 29.13, Release-6-7 6.0, BBN 35.0, BFLY 8.0, Experimental PARCL 8.0, microcode TMC5-IO4-COL-MIC 388, FEP 127, fep0:>v127-lisp.flod(44), fep0:>v127-loaders.flod(44), fep0:>v127-info.flod(44), fep0:>v127-debug.flod(31), on Cod: I'm using the 12/2/86 version of PCL on a Symbolics machine. I have defined a function called my-fun as (defun my-fun () nil). I get the following error when I call (make-specializable 'my-fun). What gives? >>Trap: The argument given to the CAR instruction, #, was not a locative, a list, or NIL. While in the function REMPROP  PCL:|Method REMOVE-DYNAMIC-SLOT-USING-CLASS BASIC-CLASS|  (:INTERNAL (:INTERNAL #:G6784 0) 0) REMPROP: (P.C. = 31) Arg 0 (SI:SYM): # Arg 1 (SI:INDICATOR): PCL:PRETTY-ARGLIST Local 2 (SI:PLLOC): # Local 3: T Local 4 (SI:PL): # Local 5 (SI:PPL): # PCL:|Method REMOVE-DYNAMIC-SLOT-USING-CLASS BASIC-CLASS|: (P.C. = 4) (from PARCL: PARCL; CLASS-SLOTS) Arg 0 (PCL:CLASS): # Arg 1 (PCL:OBJECT): # Arg 2 (PCL:SLOT-NAME): PCL:PRETTY-ARGLIST (:INTERNAL (:INTERNAL #:G6784 0) 0): (P.C. = 45) Arg 0 (COMPILER:.LEXICAL-ENVIRONMENT-POINTER.): (# PCL:|Method REMOVE-DYNAMIC-SLOT-USING-CLASS BASIC-CLASS| NIL #) Arg 1 (PCL:|Discriminating Function Arg 0|): # Arg 2 (PCL:|Discriminating Function Arg 1|): # Arg 3 (PCL:|Discriminating Function Arg 2|): PCL:PRETTY-ARGLIST PCL:REMOVE-DYNAMIC-SLOT: (P.C. = 6) (from PARCL: PARCL; BRAID) Arg 0 (PCL:OBJECT): # Arg 1 (PCL:SLOT-NAME): PCL:PRETTY-ARGLIST (:INTERNAL PCL:MAKE-SPECIALIZABLE 0): (P.C. = 141) Arg 0 (COMPILER:.LEXICAL-ENVIRONMENT-POINTER.): # Rest arg: NIL PCL:MAKE-SPECIALIZABLE: (P.C. = 23) (from PARCL: PARCL; METHODS) Arg 0 (PCL:FUNCTION-NAME): PCL:MY-FUN Rest arg (PCL:OPTIONS): NIL SI:*EVAL: (P.C. = 401) Arg 0 (SI:FORM): (PCL:MAKE-SPECIALIZABLE (QUOTE PCL:MY-FUN)) Local 0 (SI:FORM): NIL --Defaulted args:-- Arg 1 (SI:ENV): NIL Arg 2 (SI:HOOK): NIL (:INTERNAL SI:LISP-COMMAND-LOOP-INTERNAL 0): (P.C. = 152) Arg 0 (COMPILER:.LEXICAL-ENVIRONMENT-POINTER.): # Rest of stack: TV:WITH-NOTIFICATION-MODE-INTERNAL: (P.C. = 16) SI:LISP-COMMAND-LOOP-INTERNAL: (P.C. = 54) SI:LISP-COMMAND-LOOP: (P.C. = 67) SI:COMMON-LISP-TOP-LEVEL: (P.C. = 46) SI:PROCESS-TOP-LEVEL: (P.C. = 54)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 13 Jan 87 23:58:03 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 13 Jan 87 14:44:57 PST Received: from JUNCO.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92747; Tue 13-Jan-87 14:23:50 EST Date: Tue, 13 Jan 87 14:23 EST From: Sonya E. Keene Subject: Re: Issues for the CLOS committee to start focussing on To: Bobrow.pa@Xerox.COM cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870113-103835-6035@Xerox> Message-ID: <870113142321.8.SKEENE@JUNCO.SCRC.Symbolics.COM> Line-fold: No Date: 13 Jan 87 10:38 PST From: Danny Bobrow Date: 8 Jan 87 23:48 PST From: Danny Bobrow Class variables. (Discussion is ongoing, probably almost finished) What is your belief about the state of this. I made a detailed suggestion last. Danny, I assume you're asking me, since I was the TO: recipient. My belief is that it hasn't converged yet, but is close. I don't think I've read your detailed suggestion carefully yet. This issue isn't one of the next three on my priority list; if you'd rather I thought about this first, though, let me know and I will. Sonya said she would write up what I had suggested in English, and we can go from there. (Right Sonya?) danny Right, Danny. I've written up a draft of this, and given it to Dave for sanity checking and to get answers to some questions that came up. We'll probably have it ready for public viewing sometime today or tomorrow.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 13 Jan 87 13:54:45 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 13 Jan 87 10:42:50 PST Received: from Cabernet.ms by ArpaGateway.ms ; 13 JAN 87 10:38:35 PST Date: 13 Jan 87 10:38 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Issues for the CLOS committee to start focussing on In-reply-to: David A. Moon 's message of Mon, 12 Jan 87 22:43 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870113-103835-6035@Xerox> Date: 8 Jan 87 23:48 PST From: Danny Bobrow Class variables. (Discussion is ongoing, probably almost finished) What is your belief about the state of this. I made a detailed suggestion last. Danny, I assume you're asking me, since I was the TO: recipient. My belief is that it hasn't converged yet, but is close. I don't think I've read your detailed suggestion carefully yet. This issue isn't one of the next three on my priority list; if you'd rather I thought about this first, though, let me know and I will. Sonya said she would write up what I had suggested in English, and we can go from there. (Right Sonya?) danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 22:58:45 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 19:49:50 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42053; Mon 12-Jan-87 22:49:11 EST Date: Mon, 12 Jan 87 22:48 EST From: David A. Moon Subject: For the Record To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 11 Jan 87 00:01 EST from Dick Gabriel Message-ID: <870112224807.6.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 10 Jan 87 2101 PST From: Dick Gabriel Was I mistaken in believing that Moon's counter to Gregor's code should have been: (define-method-combination mine () ((methods (*))) (grovel-my-method-combination #'make-method-call methods)) (defun grovel-my-method-combination (make-method-call methods) .. (funcall make-method-call methods :operator 'foo) ..) Right. What an embarrassing and understandability-destroying typo! (I had (funcall #'make-method-call methods :operator 'foo) !)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 22:55:47 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 19:45:22 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42048; Mon 12-Jan-87 22:44:29 EST Date: Mon, 12 Jan 87 22:43 EST From: David A. Moon Subject: Re: Issues for the CLOS committee to start focussing on To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870108-234851-2441@Xerox> Message-ID: <870112224325.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 8 Jan 87 23:48 PST From: Danny Bobrow Class variables. (Discussion is ongoing, probably almost finished) What is your belief about the state of this. I made a detailed suggestion last. Danny, I assume you're asking me, since I was the TO: recipient. My belief is that it hasn't converged yet, but is close. I don't think I've read your detailed suggestion carefully yet. This issue isn't one of the next three on my priority list; if you'd rather I thought about this first, though, let me know and I will.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 21:45:20 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 18:36:05 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 42006; Mon 12-Jan-87 21:35:10 EST Date: Mon, 12 Jan 87 21:34 EST From: David A. Moon Subject: Environment for initial value form To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 11 Jan 87 15:08 EST from Dick Gabriel Message-ID: <870112213405.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 11 Jan 87 1208 PST From: Dick Gabriel The lexical environmemt in which the defclass happens is right. Everyone who spoke up agrees with this, but the document doesn't say it yet. Let's not drop this one through the cracks.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 21:35:38 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 18:28:30 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 41998; Mon 12-Jan-87 21:27:55 EST Date: Mon, 12 Jan 87 21:26 EST From: David A. Moon Subject: For the Record To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 11 Jan 87 00:01 EST from Dick Gabriel Message-ID: <870112212650.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 10 Jan 87 2101 PST From: Dick Gabriel 4. Some potential users have asked me to bring up the subject of CALL-NEXT-METHOD passing altered arguments to the next method. This has been disallowed because the next method might get arguments that don't conform to its parameter qualifiers. Is there further discussion? I think there should be. I've added this to the list of issues on my whiteboard, whence it will likely migrate to more permanent storage. However, we may not get to this before the Feb 4 deadline, since there are more critical things to do first. Note that the issue of CALL-NEXT-METHOD passing altered arguments to the next method is very closely connected with the issue of MAKE-METHOD-CALL passing altered arguments.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 12 Jan 87 19:44:47 EST Received: from Semillon.ms by ArpaGateway.ms ; 12 JAN 87 15:21:31 PST Return-Path: Received: from ucbvax.Berkeley.EDU by Xerox.COM ; 12 JAN 87 15:19:37 PST Received: by ucbvax.Berkeley.EDU (5.53/1.20) id AA22916; Mon, 12 Jan 87 14:53:52 PST Received: by shambhala.berkeley.edu (1.2/5.6) id AA00880; Mon, 12 Jan 87 14:47:53 pst From: ricks%shambhala.Berkeley.EDU@BERKELEY.EDU (Rick L Spickelmier) Message-Id: <8701122247.AA00880@shambhala.berkeley.edu> Date: 12 Jan 87 14:47 PST (Monday) To: commonloops.pa@Xerox.COM Subject: additions for VAXLISP Here are a few things that can be added to vaxl-low.lsp and test.lsp Rick Spickelmier UC Berkeley ;;;; ;;; add to vaxl-low.lsp ;;; (defun function-arglist (func) (system::function-lambda-vars (symbol-function func))) ;;; ;;; this probably does more than is necessary! ;;; (defmacro without-interrupts (&body body) `(critical-section ,@body)) ;;;; ;;; add to test.lsp ;;; (defvar *without-errors* (or #+Symbolics #'(lambda (form) `(multiple-value-bind (.values. .errorp.) (si::errset ,form nil) (declare (ignore .values.)) .errorp.)) ;; errset returns nil for failure, (result) for no-error ;; thus it should work for 'do-test' #+VAXLISP #'(lambda (form) (system::errset ,form)) nil))  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 18:57:09 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 15:46:47 PST Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92390; Mon 12-Jan-87 18:47:52 EST Date: Mon, 12 Jan 87 18:45 EST From: David A. Moon Subject: Re: Method Combination Proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870108-232001-2402@Xerox> Message-ID: <870112184516.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Here are answers reflecting what I put into the document. Date: 8 Jan 87 23:19 PST From: Danny Bobrow If I was going to do those programming environment facilities, I would try to do them by calling the method-combination function and seeing what happens, rather than by adding a new syntax to be used in the define-method-combination specifically to convey that information. This is similar to the suggestion that the best way to find out what methods are actually called is to call the method-combination function and analyze the Lisp form it returns, rather than adding a new syntax for it to return a list of methods. I don't understand how this helps in finding unacceptable methods (with bad method qualifiers). There can be any number of reasons (e.g. shadowing with no call-next-method) why the result of a method combination does not include some applicable methods. So the result cannot be what is checked. It must then be some use of the selection of methods that is used. This is not specified (or only implicitly) by the template language (and by FIND-METHODS). I straightened this out, I think (as much as I could without depending on the condition system that has been proposed but not yet adopted). There is a function, INVALID-METHOD-ERROR, which is called with the offending method object as an argument, along with a string error message. The programming environment can make this function do what it needs. Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity... Yes, and I haired it up (sorry). But, I think the language for FIND-METHODS is an independent issue from whether FIND-METHODS should be used for specifying subsets of methods or only the template language. The real issue I believe is whether FIND-METHODS can only be used in a define-method-combination body (in which case probably the template language is as good as having the form) or whether there can be sub-functions that use it; clearly they cannot have the template language. I prefer having subfunctions have the same capabiities as forms in the main body. I agree with the last sentence and I tried to make that the case as much as possible in the latest version. It's not quite perfect but I think it's adequate. (define-method-combination mine () ((methods (*))) (grovel-my-method-combination #'make-method-call methods)) I found this very clever. However, I prefer to have the auxiliary information in the metaobjects for the reasons you give. This was so clever that I flushed it. Consulting notes and the rationale section, we had already decided that we shouldn't do it this way and that the extra information should be passed as special variables, not lexically. So I changed it to work that way. With respect to the method-selection process, I was embarrased to hear an argument I always use thrown back at me "this would be done in Lisp instead of a special embedded language") However, doesn't this put all the error checking in Lisp, even for the simple cases. I was proposing a simple error checking template language with :qualifier-set. Or, perhaps I just missed the dual purpose of the method-group specifiers, to select AND error check the set of applicable methods. The explanation and motivation should be much better and clearer now. Are you saying that in place of the qualifier patterns one could put the name of a predicate, in cases where the simple pattern match language wasn't strong enough? That seems like a good idea. If we go with method-group specifiers, that is what I meant. The predicate gets as an argument the list of all methods not yet selected in the generic-function, and returns a subset. I put this in, except I made the predicate get applied separately to each method (actually to the qualifier list of the method), since I thought that would be easier for the user and it's no less general. Also it shouldn't be called a predicate if the value isn't true/false. If I had to rank my objections, my strongest one is against the lambda list. I'd like to understand why. Four reasons: 1) It hairs up the syntax of both define-method-combination and defgeneric-options This is weak. I don't see any significant complexity increase. 2) With no good simple example of its use, its utility is much in doubt in my mind This is strong. 3) In thinking about defining the arguments to the methods in the meta-object protocol (e.g. compute-effective-method) I don't want to have extra arguments sometimes. It's just a list, not a variable number of arguments. (We're using the word "arguments" to mean two different things. One is the arguments given to the compute-effective-method generic function; the other is the syntax of the :method-combination option to defgeneric-options, which includes a "name" possibly followed by "arguments."). I think I wrote this more clearly in the latest document; let me know how you like it. 4) Without this argument list, there is no need for a simple form of DEFINE-METHOD-COMBINATION since the one form is simple enough. LEAN proposal. This is not true; I hope I've made things clear enough in the latest version of the document that it's now obvious why it's not true. In spite of #2, I left the lambda-list in, because of the need to pass in the generic-function. We can discuss that more if it's a problem. If the method combination arguments are constants for the generic function, then a specialized generic function with such state is sufficient. I don't think a special magic way to put information into slots of the generic-function and another special magic way to get it out again can be considered less hairy syntax than a lambda-list. Programmers are already familiar with lambda-lists. It does imply though that some mechanism must be found for the user to get access to the generic-function in the body of define-method-combination. You said you had one you liked in Flavors -- what is it. I didn't say that. We have one I -dislike-, which is that a variable with a magic name in a magic package is bound to the generic-function. Do we want to hair up defgeneric-options to allow extra state to be specified? For example, one option of defgeneric-options could be (:slots slot-name-1 slot-value1 ...) I find this preferable since it extends a much more general facility to the user. I find this definitely excessive. It's using an H-bomb to kill a fly, and also is syntactically poor because not all of the :method-combination information would be in one place in the defgeneric-options. In addition, I think the body of the method combination should have access to the generic function in question. It can't get it from the methods since methods can be on more than one generic function. I don't think that has been agreed to. It seems to be simpler to allow sharing of method-functions, but not sharing of method-objects. After some more thought on this issue, I can't find a good case against it. The form of argument against should be that one wants to change some part of a method (say its function) and have this effect seen in two generic functions. I cannot think of a plausible scenario. I agree with you here, but... Does this solve the access to the generic-function for method-combination? Only if in the place where the generic function is required there is a guarantee that a method is available. Is that always possible? ...I wasn't so sure that getting the generic-function from the methods was a good idea after all, because I can see cases where a method isn't easily available, and because we might change our mind for some reason about the data structure having a reference from a method to its generic-function, so it didn't seem wise to depend on it. Instead I just made the generic-function be passed as an argument, which seems simplest all around except that you have to put in a declare ignore if you don't use it, to be strict Common Lisp. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an appropriate mechanism for dealing with this optimization. It may just be the name which is upsetting me, I am not sure yet. The other way to deal with this is to make it a keyword argument to make-method-call, which defaults to (eq operator 'progn). I would be happy with that; in fact I think it's what I proposed originally, but when we discussed this in Menlo Park, the change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT was made (I forget who proposed it and what the arguments were). Note that the simple form of DEFINE-METHOD-COMBINATION would need this keyword argument too. The objections to the keyword were 1) it was an extra keyword Better an extra keyword than an extra function, surely. 2) this information was something that was useful in more than this context. Other method-combination types and other program constructing programs can use the same information. Can we push this problem into the COMPILER group for CommonLisp, and assume that they will propose something like this? It seems inappropriate for the object standard. I decided that it was a mistake to associate this with the compiler, and that this was really highly specific to method-combination, so I took out the extra function and put the extra keyword back in. I am now completely convinced that it's wrong to do this with a function. If people want to argue that it shouldn't be done at all, we can talk about that. I put some motivational explanation into the document. To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION is similar to the syntax of DEFMACRO and DEFSETF. By the way, Flavors' DEFINE-METHOD-COMBINATION doesn't allow doc-strings. Should we leave this out and allow this to be something beat back in by the committee if necessary (Gives them a chance to piss on something). I think it's better to be consistent. There are more useful places for them to piss.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 18:36:19 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 12 Jan 87 15:30:11 PST Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 92382; Mon 12-Jan-87 18:31:20 EST Date: Mon, 12 Jan 87 18:28 EST From: David A. Moon Subject: Documents updated for method combination To: Common-Lisp-Object-System@SU-AI.ARPA Message-ID: <870112182842.8.MOON@EUPHRATES.SCRC.Symbolics.COM> I have updated CONCEP.TEX[CLS,LSP] for method combination, and copied it to CONCEP.8. The file DMC.FUN[CLS,LSP] contains sections to be inserted into the functions document when that document unfreezes, however these sections haven't been fully converted to TEX yet. This is the updating I promised to do last Friday (it took longer than expected). I believe this reflects the result of the discussions we've had over the mail, but if I have slighted anyone's point of view I apologize, and I encourage you to write up a dissenting proposal and add it to the file. I plan to turn my own attention to some of the other outstanding issues, in an effort to get to a reasonable (but not unchangeably final by any means) document by the next X3J13 meeting, so I won't be doing anything more on method combination this month if I can help it.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 01:46:01 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Jan 87 22:40:03 PST Received: from Cabernet.ms by ArpaGateway.ms ; 11 JAN 87 22:31:28 PST Date: 11 Jan 87 22:31 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: For the Record In-reply-to: Dick Gabriel 's message of 10 Jan 87 21:01 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870111-223128-4273@Xerox> 4. Some potential users have asked me to bring up the subject of CALL-NEXT-METHOD passing altered arguments to the next method. This has been disallowed because the next method might get arguments that don't conform to its parameter qualifiers. Is there further discussion? I don't think this should be disallowed. I think argument checking should be done, and an error signalled if types of discriminated arguments have changed. In most simple cases, I would think this check can be compiled away (no rebinding or setting of the incoming arguments, and the name used in the call). An (ugly) alternative is to provide keyword syntax of some sort for changing just those arguments desired (call-next-method x new-value-of-x). 1. I like Moon's expanded pattern language proposal: It's the one where the third subform of define-method-combination becomes ({ (variable {qualifier-pattern}+ {keyword argument}*) | (variable predicate-symbol {keyword argument}*) }*) In case I wasn't clear, I like this extension too. The only question was whether we should have a patter language, and always use Lisp in a subfunction. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 12 Jan 87 01:36:26 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Jan 87 22:30:14 PST Received: from Cabernet.ms by ArpaGateway.ms ; 11 JAN 87 22:22:59 PST Date: 11 Jan 87 22:22 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Issues for the CLOS committee to start focussing on In-reply-to: Dick Gabriel 's message of 11 Jan 87 12:07 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870111-222259-4265@Xerox> Terminology Is the following used consistently? "An instance q is of type X if (CLASS q) is X or a subclass of X; that is X is at or above the (CLASS q)" Is "type" the right word here? Seems right to me, given the joining of the type and class spaces. The name for standard method combination in the concepts document, and elsewhere whould be "standard" not daemon. My description requires that we make the class DAG a lattice, which means a bottom as well as a top element. We haven't decided this, but I don't think it's a big deal to do it. The only issue here is making it clear and getting the right name for the bottom. From the point of view of agreeing with the type system, NIL is the right name for the bottom, since NIL is a defined Common Lisp type. But what happens when people evaluate (CLASS-NAMED NIL). Do they get a real class? Or should (CLASS-NAMED NIL) signal an error? If we have unnamed classes, then (NEQ (CLASS-NAMED (CLASS-NAME )) ) which is OK with me. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 11 Jan 87 15:16:38 EST Date: 11 Jan 87 1208 PST From: Dick Gabriel Subject: Environment for initial value form To: common-lisp-object-system@SAIL.STANFORD.EDU The lexical environmemt in which the defclass happens is right. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 11 Jan 87 15:12:45 EST Date: 11 Jan 87 1207 PST From: Dick Gabriel Subject: Issues for the CLOS committee to start focussing on To: common-lisp-object-system@SAIL.STANFORD.EDU Here is a reproduction of part of Moon's message with some statements about how things are going on the issues [enclosed in square brackets]. Consistent terminology - names for relationships among classes [In the concepts file I have made the following definitions and terminology conventions: ``direct superclass'' means immediate parent. ``direct subclass'' means immediate daughter. ``superclass'' means direct superclass or direct superclass of a direct superclass or etc. ``subclass'' is similar. I've defined the phrase ``classes at or above a given class'' to mean what ``component'' means in New Flavors documentation. It means the set of superclasses of a class along with the class itself. Mathematics provides no help except that we could chose to define a class to be a superclass of itself.] - names for predefined classes & other interesting entities [I did nothing here.] - describing the terminology at the front of the document [The concepts file, being the front of the document, defines these terms as it goes.] - making sure the document adheres everywhere to the chosen terminology (this may have been resolved already, but we were still discussing it quite recently) [The concepts file adheres everywhere. If people agree to the way it reads, I'll extend it to the functions file.] Method-combination. [This has two aspects: the general theory of how generic functions cause method combination to happen and the syntax of defining new method combination types. I took Sonya's text for the first aspect and tried to make it more understandable - I think it's a little better now. I think the hard part was explaining why it works like macro expansion instead of simply doing it.] The class precedence rules, description, and algorithm. To a certain extent these are three separate issues. (Dick has been working on this, but I don't think it's resolved yet) [I added a test description of the rules based on the topological sort approach in concepts. My description still recommends optionally signalling errors in cases where multiple orders are possible but preorder has disambiguated. I think there is a consensus to remove this, and I will as soon as Sonya is finished with the file. I think it reads pretty well. It might be a good idea to include, as an implementation note, a description of Moon's rules and algorithm as an example of an equivalent implementation, or of Danny's, but I don't plan to do it. My description requires that we make the class DAG a lattice, which means a bottom as well as a top element. We haven't decided this, but I don't think it's a big deal to do it. If we don't do it and go with alternatives like calling it a lattice though it isn't, I think we risk ridicule. The one reasonable alternative is to define it to be a DAG with a distiniguished element, and when we compute the CPL, we get a local lattice.] -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 11 Jan 87 00:09:59 EST Date: 10 Jan 87 2101 PST From: Dick Gabriel Subject: For the Record To: common-lisp-object-system@SAIL.STANFORD.EDU 1. I like Moon's expanded pattern language proposal: It's the one where the third subform of define-method-combination becomes ({ (variable {qualifier-pattern}+ {keyword argument}*) | (variable predicate-symbol {keyword argument}*) }*) 2. I basically don't like pattern languages, but in this case I believe the alternatives are worse. Many pattern languages I know of use the character ``*'' to mean ``match 0 or more items.'' This minor objection can be ignored. 3. I believe Moon's analysis of make-method-combination and why it makes sense to not explicitly pass the so-called ``id'' information. Was I mistaken in believing that Moon's counter to Gregor's code should have been: (define-method-combination mine () ((methods (*))) (grovel-my-method-combination #'make-method-call methods)) (defun grovel-my-method-combination (make-method-call methods) .. (funcall make-method-call methods :operator 'foo) ..) 4. Some potential users have asked me to bring up the subject of CALL-NEXT-METHOD passing altered arguments to the next method. This has been disallowed because the next method might get arguments that don't conform to its parameter qualifiers. Is there further discussion? -rpg-  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 9 Jan 87 23:31:30 EST Received: from Semillon.ms by ArpaGateway.ms ; 09 JAN 87 19:09:36 PST Return-Path: Received: from cogsci.berkeley.edu ([128.32.130.5]) by Xerox.COM ; 09 JAN 87 19:07:57 PST Received: by cogsci.berkeley.edu (5.57/1.20) id AA18277; Fri, 9 Jan 87 19:07:47 PST Date: Fri, 9 Jan 87 19:07:47 PST From: ehl%cogsci.Berkeley.EDU@berkeley.edu (Edward H. Lay) Message-Id: <8701100307.AA18277@cogsci.berkeley.edu> To: DMACLAUGHLIN@bbng.arpa Cc: commonloops.pa@Xerox.COM ...other stuff... 4) I ran into a problem with the default printing method. It seems that this method performs a funcall on the slot accessor for each slot in the object, without checking to see if the slot has an accessor method defined for it, which leads to an error. Perhaps it should perform this check. I know you can get around it be defining a separate print-instance method, but I don't think it should be necessary to have to define one for every class which may have a slot with no accessor. (On the other hand, I feel that having a slot without an accessor is a little silly--why bother having the slot at all? Maybe you can enlighten me on this subject.) ...more other stuff... The problem isn't withthe printing method it's with the default all-slots method. You'll run into the same problem if you (for example) try and change the class of your instance. I've patched my version of PCL to look up the slot name (rather than the slot accessor) and then call get-slot in the all-slots method. ed lay  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 20:54:54 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jan 87 17:44:10 PST Received: from Cabernet.ms by ArpaGateway.ms ; 09 JAN 87 16:59:38 PST Date: 9 Jan 87 16:59 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Class Precedence List: Rebuttal to Danny In-reply-to: Dick Gabriel 's message of 09 Jan 87 11:54 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870109-165938-3473@Xerox> Danny writes: ``This primacy [of the preorder] is good I claim, because in the simple (and usual) case it describes the result of the sort.'' I guess Danny means that he expects most people will build a tree, except for the lattice requirement of the class named T being at the top; in this case he's right. But, if you have almost any nontrivial structure to the upper part of the lattice, it is a big mistake for users to adopt this mental model. There is a simple rule. If any mixin appears more than once, and not in last position in the local supers, then the user must apply the movement rules. I claim this is relatively rare, although it is easy to construct examples. (Dave do you have data on this? How many flavors have components that share mixins where the mixins are not last in the chain?) Thus it is both easy to construct the usual list, and easy to know when the movement rules are to apply. The example you give is clearly has the property I gave, and the movement rule is easy for this case. (defclass c1 () ()) (defclass c2 () ()) (defclass c3 () ()) (defclass e1 (c1) ()) (defclass e2 (c2) ()) (defclass e3 (c3) ()) (defclass e4 (e3 e2 e1) ()) (defclass e5 (c1 c2) ()) (defclass e6 (c2 c3) ()) (defclass e7 (e5 e6 e4) ()) He eliminates duplicates from the front of the list: (E7 E5 E6 E4 E3 C3 E2 C2 E1 C1) Now going from the left, C3 depends directly on C2, so move it past all of it dependendents (this means C1). Then coming to C2, move it past its dependents getting (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3) Danny writes: ``It is primary in how people will try to simulate the algorithm.'' I think we should discourage users from using preorder to simulate the algorithm. They will lose unless the lattice is mostly like a tree. I think users knowing that the local precedence orders are very important and providing tools to look at the total orders at classes is the only good option. I think it is foolhardy to try to discourage programmers from thinking about algorithms. They are not mathematicians. Who could argue that it is bad to provide tools to look at the total orders at classes, but for understnadability off line, they should have an easy way to think about construction of the list. Danny asks: ``How does the topological sort algorithm state the error condition about loops?'' The sort terminates when it can not find a class that is preceeded by no others. If, when the sort terminates, there are classes left to be sorted, then there is a loop in the relations. I don't understand. If e3 in the above example had (c3 c2) as supers, where would it fail? Danny asks: ``What determines the order of fruit and spice [in Moon's algorithm]? What determines the order in your algorithm except the preorder?'' In Moon's algorithm the preorder determines it along with the fact that the local precedence orders never veto the preorder constraint. In my algorithm the preorder arbitrates. Sounds like the preorder determines it. Moons constraints don't determine it though -- only the algorithm (except for the "hidden" flavor rule he told us about.) The point of this variable is that the explicit constraints that the user writes - the subclass-superclass relations and the local precedence orders - ought to uniquely determine the total order, because these are the only things that he directly manipulates. When the class precedence list computation relies on the preorder, it is looking at some more global structure of the lattice when the direct constraints underconstrain the total order. But you ignore the fact the the user does not want to directly constrain the total order. If two mixins C1 and D1 live in a hierarchy, and C1 inherits from C2 inherits from C3, and D1 from D2 and D2 from D3, then anything that contains C and D will have many possible total orders. Did I care? Didn't I want a fixed one obeying Moon's hidden rule, so that splitting a class doesn't change behavior. So no variable either. I think the document requires a ``"meaningless"'' bottom element, which is the class named NIL. We could merely apologize for the slight misuse of the term "lattice" and call it one from then on. Possbily alluding to the fact that the user has been allowed to not be burdened with the NIL class. I've already explained why I think your algorithm results in potential confusion in readers of a description of it. Of course, your algorithm has been, up to now, subjected to no very strenuous writing onslaught. I think I have answered you, and good writing is indeed called for. danny  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 9 Jan 87 19:39:51 EST Received: from Semillon.ms by ArpaGateway.ms ; 09 JAN 87 14:09:31 PST Return-Path: Received: from ingres.Berkeley.EDU ([128.32.156.105]) by Xerox.COM ; 09 JAN 87 14:06:28 PST Received: by ingres.Berkeley.EDU (5.57/1.14) id AA09828; Fri, 9 Jan 87 14:06:11 PST Date: Fri, 9 Jan 87 14:06:11 PST From: dcmartin@ingres.berkeley.edu (David C. Martin) Message-Id: <8701092206.AA09828@ingres.Berkeley.EDU> To: commonloops.pa@Xerox.COM Subject: specializing macros There is a macro called ``time'' in the lisp package of ExCL. When I attempt to specialize this macro w/ make-specializable it barfs since there is no funcallable object for ``time''. My quick workaround was to shadow the function time, but this seems sort of foolish as make-specializable should be able to handle this situation. Comments? dcm  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 9 Jan 87 19:39:34 EST Received: from Semillon.ms by ArpaGateway.ms ; 09 JAN 87 13:57:44 PST Return-Path: Received: from H.CS.CMU.EDU ([128.2.254.156]) by Xerox.COM ; 09 JAN 87 13:55:08 PST Date: 9 Jan 87 16:47 EST From: Rick.Busdiecker@h.cs.cmu.edu To: CommonLoops.PA@Xerox.COM Subject: vector class? Message-Id: <537227227/rfb@h.cs.cmu.edu> Is there a way to discriminate on a vector? I tried: * (defmeth id ((x vector)) :vector) id however when I try to use it: * (id (vector)) Error in function class-of. Can't determine class of #() The same sort of thing worked just as a I expected it to on strings. Why is this a problem for vectors? Rick  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 17:05:49 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 13:59:06 PST Received: from JUNCO.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91936; Fri 9-Jan-87 16:59:49 EST Date: Fri, 9 Jan 87 16:56 EST From: Sonya E. Keene Subject: new version of concepts chapter To: common-lisp-object-system@sail.stanford.edu Message-ID: <870109165636.4.SKEENE@JUNCO.SCRC.Symbolics.COM> I wrote a new version of concepts.tex (and copied it to concepts.7). The changes were mainly editorial. I still want a "hold" on the file, because I need to make more changes on Monday.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 16:57:57 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 13:49:04 PST Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 91932; Fri 9-Jan-87 16:50:07 EST Date: Fri, 9 Jan 87 16:47 EST From: David A. Moon Subject: Re: What's left to do To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870108-213053-2356@Xerox> Message-ID: <870109164709.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 8 Jan 87 21:30 PST From: Danny Bobrow 2,3. Change-class and Initialization protocol. Are their explicit outstanding questions, or are Gregor's messages the current last word? You've probably seen my message on this by now, but just in case: I haven't started on these yet, since I wanted to concentrate on finishing method-combination first. I expect that there are a lot of outstanding questions, in spite of the quietness of the mail. I plan to work on both of these (initialization first) next week. I anticipate a lot of interruptions and other demands on my time next week, but I hope to get through these issues in spite of that.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 15:59:19 EST Date: 09 Jan 87 1154 PST From: Dick Gabriel Subject: Class Precedence List: Rebuttal to Danny To: common-lisp-object-system@SAIL.STANFORD.EDU Danny writes: ``This primacy [of the preorder] is good I claim, because in the simple (and usual) case it describes the result of the sort.'' I guess Danny means that he expects most people will build a tree, except for the lattice requirement of the class named T being at the top; in this case he's right. But, if you have almost any nontrivial structure to the upper part of the lattice, it is a big mistake for users to adopt this mental model. Here is a possibly too large and too ugly example: (defclass c1 () ()) (defclass c2 () ()) (defclass c3 () ()) (defclass e1 (c1) ()) (defclass e2 (c2) ()) (defclass e3 (c3) ()) (defclass e4 (e3 e2 e1) ()) (defclass e5 (c1 c2) ()) (defclass e6 (c2 c3) ()) (defclass e7 (e5 e6 e4) ()) If a user does a preorder treewalk to guess how the total order will look, he will get the following. 1. If he eliminates duplicates from the front of the list: (E7 E5 E6 E4 E3 C3 E2 C2 E1 C1) 2. If he eliminates duplicates from the rear of the list: (E7 E5 C1 C2 E6 C3 E4 E3 E2 E1) Meanwhile, the total order looks like: (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3) Well, option 1 is correct to the halfway point, so I suppose half right is better than nothing. On the other hand, option 2 gets the critical and curious relatives order of (E3,E2,E1) and (C1,C2,C3) right. Hard to know which a user would be better off with. I should mention, as a curiosity, that my algorithm makes no appeal to the preorder when computing the class precedence list for E7: The user would be, therefore, encouraged to use the very thing that is irrelevant to the total order to intuit that total order. Danny writes: ``It is primary in how people will try to simulate the algorithm.'' I think we should discourage users from using preorder to simulate the algorithm. They will lose unless the lattice is mostly like a tree. I think users knowing that the local precedence orders are very important and providing tools to look at the total orders at classes is the only good option. Danny writes: ``There is no question about whether the algorithm terminates....'' I agreed it is clear to me that the algorithm terminates. I stated that a reader might be puzzled by this question. Danny asks: ``How does the topological sort algorithm state the error condition about loops?'' The sort terminates when it can not find a class that is preceeded by no others. If, when the sort terminates, there are classes left to be sorted, then there is a loop in the relations. Danny writes: `` EXAMPLE 2 (not repeated here) admits a single possibility by his rules, which is (pie apple fruit cinnamon spice food) Not by my interpretation of his rules....'' This is the example Moon uses in the document ``Common Lisp Classes: A Draft Object-oriented Standard'' on page 30 under the heading ``Example of a Tree Walk.'' I claim it admits a single possibility by Moon's interpretation of Moon's rules. Danny asks: ``What determines the order of fruit and spice [in Moon's algorithm]? What determines the order in your algorithm except the preorder?'' In Moon's algorithm the preorder determines it along with the fact that the local precedence orders never veto the preorder constraint. In my algorithm the preorder arbitrates. Danny writes: `` [quote: rpg] I also propose that implementations be encouraged to offer a means of warning or signalling an error every time that appeal is made to the preorder. [unquote: rpg] Again this is the usual case where one has independent mixins with superclasses. So no warning please.'' I suppose I should be more precise with my language. I propose that implementations be encouraged to provide a special variable called *warn-on-nondeterminism-in-topological-sort*, for example, whose default value is NIL and such that when its value is non-null the algorithm that computes the class precedence list warns the user (or signals an error) when it encounters a situation in which the topological sort cannot uniquely determine a total order from the partial orders. The point of this variable is that the explicit constraints that the user writes - the subclass-superclass relations and the local precedence orders - ought to uniquely determine the total order, because these are the only things that he directly manipulates. When the class precedence list computation relies on the preorder, it is looking at some more global structure of the lattice when the direct constraints underconstrain the total order. ``So no warning please'' translates into (setq *warn...* nil). Well, I won't press on this issue too much. I think, however, that without tools to display the class precedence list programmers will be stumped a lot of the time. Danny writes: ``By the way, this DAG is not a lattice in that there is no "meaningful" lower bound for any two classes. But I believe we have agreed on a top of T in any event.'' I think the document requires a ``"meaningless"'' bottom element, which is the class named NIL. If we decide we don't like that, then we can describe it as a set of lattices rooted at the class named T, or as a directed acyclic graph with a distinguished element that is the class named T. I think it's nicer to say we have a lattice than a set of lattices or a directed acyclic graph, but this, I believe, is a matter of taste. Except for being able to state that one aspect of the partial order on the structure is the lattce order, there is no reason for it - we can always explain that when you compute the class precedence list for a class, you have a lattice with top the class named T and bottom that given class. The meaningless bottom element can have a local precedence order that reflects the order in which the classes directly above it were created. Danny concludes: ``So my conclusion is that your description is a good mathematical one, and should be included. Mine is a good operational one, and should be included. And both agree with Moon's algorithm with the other Flavors rule, so we are all right.'' I've already explained why I think your algorithm results in potential confusion in readers of a description of it. Of course, your algorithm has been, up to now, subjected to no very strenuous writing onslaught. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 09:19:18 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jan 87 06:12:37 PST Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39604; Fri 9-Jan-87 09:12:09 EST Date: Fri, 9 Jan 87 09:10 EST From: Sonya E. Keene Subject: Re: Issues for the CLOS committee to start focussing on To: Bobrow.pa@Xerox.COM cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870108-234851-2441@Xerox> Message-ID: <870109091029.3.SKEENE@JUNCO.SCRC.Symbolics.COM> Line-fold: No Date: 8 Jan 87 23:48 PST From: Danny Bobrow We need to define quite explicitly the inheritance behavior of class options and slot options. There should be a table listing each option and showing how it inherits. I made a set of suggestions for this. If one of the writers could turn that into English and find where the holes are, I would be glad to follow up (I don't have time for extensive writing at the moment). I'll get to work on this. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 02:54:11 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:49:08 PST Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:48:51 PST Date: 8 Jan 87 23:48 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Issues for the CLOS committee to start focussing on In-reply-to: David A. Moon 's message of Thu, 8 Jan 87 23:25 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870108-234851-2441@Xerox> We need to define quite explicitly the inheritance behavior of class options and slot options. There should be a table listing each option and showing how it inherits. I made a set of suggestions for this. If one of the writers could turn that into English and find where the holes are, I would be glad to follow up (I don't have time for extensive writing at the moment). Class variables. (Discussion is ongoing, probably almost finished) What is your belief about the state of this. I made a detailed suggestion last. Some of the functions in the Functions chapter don't make sense without the rest of meta-objects. Perhaps it should be reorganized into two chapters. I will be trying with Gregor to add as much more of the meta-object protocol as possible after he gets back at the end of next week. I would suggest sending it out even if we don't agree on all of it, but this can wait, pending seeing it. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 02:47:57 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:42:25 PST Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:42:43 PST Date: 8 Jan 87 23:42 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Lexical environment of slot default initial value forms In-reply-to: David A. Moon 's message of Thu, 8 Jan 87 19:59 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870108-234243-2424@Xerox> We discussed this and concluded that the lexical environment should be the lexical environment where the form originally appeared, i.e. the lexical environment in which defclass was evaluated, and the dynamic environment should be the one in effect at the time the form is evaluated. Sounds right. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 02:47:17 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:41:27 PST Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:41:15 PST Date: 8 Jan 87 23:41 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Class Precedence List In-reply-to: Dick Gabriel 's message of 08 Jan 87 20:01 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870108-234115-2419@Xerox> [Danny's] algorithm gives primacy to the preorder treewalk, and there is a question about whether the algorithm terminates - though it's actually easy to prove if the algorithm is stated clearly - and about how the error condition is computed. This primacy is good I claim, because in the simple (and usual) case it describes the result of the sort. It is primary in how people will try to simulate the algorithm. There is no question about whether the algorithm terminates, or the error condition (though perhaps it would be more clearly stated in terms of the partial order). How does the topological sort algorithm state the error condition about loops? EXAMPLE 2(not repeated here) admits a single possibility by his rules, which is (pie apple fruit cinnamon spice food) Not by my interpretation of his rules (not including the Flavors extra rule about superclasses). Why determines the order of fruit and spice? What determines the order in your algorithm except the preorder. I also propose that implementations be encouraged to offer a means of warning or signalling an error every time that appeal is made to the preorder. Again this is the usual case where one has independent mixins with superclasses. So no warning please. By the way, this DAG is not a lattice in that there is no "meaningful" lower bound for any two classes. But I believe we have agreed on a top of T in any event. So my conclusion is that your description is a good mathematical one, and should be included. Mine is a good operational one, and should be included. And both agree with Moon's algorithm with the other Flavors rule, so we are all right. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 02:30:47 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 23:20:57 PST Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 23:20:01 PST Date: 8 Jan 87 23:19 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Method Combination Proposal In-reply-to: David A. Moon 's message of Tue, 6 Jan 87 21:57 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870108-232001-2402@Xerox> I don't understand this reference to environment information. I have never proposed any special programming environment facilities here, other than the :description thing to control printed representation. You're probably referring to my insistence that macros that don't check their arguments, but just ignore anything they don't recognize, are bad; I think this is a language issue, not an environment issue. Yes the :description is an environmental issue, and when error control is done is environmental. I don't object to a macro checking its arguments. It was the checking of methods that are not found that is at issue (see next paragraph). If I was going to do those programming environment facilities, I would try to do them by calling the method-combination function and seeing what happens, rather than by adding a new syntax to be used in the define-method-combination specifically to convey that information. This is similar to the suggestion that the best way to find out what methods are actually called is to call the method-combination function and analyze the Lisp form it returns, rather than adding a new syntax for it to return a list of methods. I don't understand how this helps in finding unacceptable methods (with bad method qualifiers). There can be any number of reasons (e.g. shadowing with no call-next-method) why the result of a method combination does not include some applicable methods. So the result cannot be what is checked. It must then be some use of the selection of methods that is used. This is not specified (or only implicitly) by the template language (and by FIND-METHODS). Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity... Yes, and I haired it up (sorry). But, I think the language for FIND-METHODS is an independent issue from whether FIND-METHODS should be used for specifying subsets of methods or only the template language. The real issue I believe is whether FIND-METHODS can only be used in a define-method-combination body (in which case probably the template language is as good as having the form) or whether there can be sub-functions that use it; clearly they cannot have the template language. I prefer having subfunctions have the same capabiities as forms in the main body. (define-method-combination mine () ((methods (*))) (grovel-my-method-combination #'make-method-call methods)) I found this very clever. However, I prefer to have the auxiliary information in the metaobjects for the reasons you give. With respect to the method-selection process, I was embarrased to hear an argument I always use thrown back at me "this would be done in Lisp instead of a special embedded language") However, doesn't this put all the error checking in Lisp, even for the simple cases. I was proposing a simple error checking template language with :qualifier-set. Or, perhaps I just missed the dual purpose of the method-group specifiers, to select AND error check the set of applicable methods. Are you saying that in place of the qualifier patterns one could put the name of a predicate, in cases where the simple pattern match language wasn't strong enough? That seems like a good idea. If we go with method-group specifiers, that is what I meant. The predicate gets as an argument the list of all methods not yet selected in the generic-function, and returns a subset. If I had to rank my objections, my strongest one is against the lambda list. I'd like to understand why. Four reasons: 1) It hairs up the syntax of both define-method-combination and defgeneric-options 2) With no good simple example of its use, its utility is much in doubt in my mind 3) In thinking about defining the arguments to the methods in the meta-object protocol (e.g. compute-effective-method) I don't want to have extra arguments sometimes. 4) Without this argument list, there is no need for a simple form of DEFINE-METHOD-COMBINATION since the one form is simple enough. LEAN proposal. If the method combination arguments are constants for the generic function, then a specialized generic function with such state is sufficient. It does imply though that some mechanism must be found for the user to get access to the generic-function in the body of define-method-combination. You said you had one you liked in Flavors -- what is it. Do we want to hair up defgeneric-options to allow extra state to be specified? For example, one option of defgeneric-options could be (:slots slot-name-1 slot-value1 ...) I find this preferable since it extends a much more general facility to the user. In addition, I think the body of the method combination should have access to the generic function in question. It can't get it from the methods since methods can be on more than one generic function. I don't think that has been agreed to. It seems to be simpler to allow sharing of method-functions, but not sharing of method-objects. After some more thought on this issue, I can't find a good case against it. The form of argument against should be that one wants to change some part of a method (say its function) and have this effect seen in two generic functions. I cannot think of a plausible scenario. Does this solve the access to the generic-function for method-combination? Only if in the place where the generic function is required there is a guarantee that a method is available. Is that always possible? PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an appropriate mechanism for dealing with this optimization. It may just be the name which is upsetting me, I am not sure yet. The other way to deal with this is to make it a keyword argument to make-method-call, which defaults to (eq operator 'progn). I would be happy with that; in fact I think it's what I proposed originally, but when we discussed this in Menlo Park, the change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT was made (I forget who proposed it and what the arguments were). Note that the simple form of DEFINE-METHOD-COMBINATION would need this keyword argument too. The objections to the keyword were 1) it was an extra keyword 2) this information was something that was useful in more than this context. Other method-combination types and other program constructing programs can use the same information. Can we push this problem into the COMPILER group for CommonLisp, and assume that they will propose something like this? It seems inappropriate for the object standard. To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION is similar to the syntax of DEFMACRO and DEFSETF. By the way, Flavors' DEFINE-METHOD-COMBINATION doesn't allow doc-strings. Should we leave this out and allow this to be something beat back in by the committee if necessary (Gives them a chance to piss on something). danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 00:37:54 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jan 87 21:30:40 PST Received: from Cabernet.ms by ArpaGateway.ms ; 08 JAN 87 21:30:53 PST Date: 8 Jan 87 21:30 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: What's left to do In-reply-to: Dick Gabriel 's message of 08 Jan 87 17:14 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870108-213053-2356@Xerox> 1. Method combination. I am planning to answer Moon on this. We are closer. 2,3. Change-class and Initialization protocol. Are their explicit outstanding questions, or are Gregor's messages the current last word? 4. Class precedence list. I think your topological sort is a reasonable specification. I would like to see my write-up in there as well. Try putting both together. Mine describes a topological sort algorithm with a preferred default order. And it describes the result of the usual case simply. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 9 Jan 87 00:07:17 EST Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 8 Jan 87 20:57:05 PST Received: from ti-csl by csnet-relay.csnet id ae03288; 8 Jan 87 23:51 EST Received: from Jenner (jenner.ARPA) by tilde id AA00349; Thu, 8 Jan 87 17:13:23 cst To: Gregor Kiczales Cc: Moon@SCRC-STONY-BROOK.ARPA, Common-Lisp-Object-System@SU-AI.ARPA Subject: Re: MAKE-METHOD arguments discussion Date: 8-Jan-87 16:06:03 From: Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Message-Id: From Moon: Oh, gross! What is the reason for wanting this? From Gregor: Let's not start this again. I don't think this is gross. In fact, I think it would be gross not to do it this way. The point is, that with meta-objects, it is more natural than before for the user to write code which grovels around in the data-structure of the object system (the meta-objects). In this kind of code, it is perfectly natural to want to invoke a method's function. I think we must start this again. The real point is: How much of low level stuff do we want to expose? The specification of the underlying metaclass protocol depends on the answer to this question. I think we want to expose enough so people can develop some new object oriented paradigms without having to reimplement everything and being able to achieve some compatibility between existing classes/metaclasses and their new ones. But then we want to provide enough room for architecture specific optimizations. Assuming that the function part of a method is funcallable outside of the context of a generic function is a severe constraint. It limits seriously the amount of optimization we can do (like distributing the overhead between the generic function and the method function). Furthermore, I don't think it is terribly useful for users to do this kind of thing. If it is, one would think that the CLOS is not too powerful since people have or want to bypass the method selection mechanism provided by the system (i.e generic function call). From Gregor: I think it is bad modularity to push whatever slot access optimization implementations may want to do into the user's face, by tacking extra arguments onto method functions where the user can see them. Specifically, I think the way this is done in flavors (with self-mapping-table as the first argument) is bad modularity, because the user should be allowed to think that when they type: (defmethod foo ((arg0 class) arg1 arg2) (equal (si:all-args-to-this-function) (list arg0 arg1 arg2))) foo will return t. Of course this particular piece of code is not such a good example, and any example will not be portable, by my point remains valid -- implementations should hide implementation details from the user. Well, hiding implementation details from the user is the very reason why your piece of code is not portable, Common Lisp never exposed the guts of a function. There is a lot of implementation techniques out there for keyword arguments. For some of them keyword arguments are not arguments but locals. So implementing actual function with more or less "real" arguments is not something new. My last point is: We will have some meta-object that the user can safely (portably) mess around with (using generic functions defined in the metaclass protocol chapter of CLOS) and some that the user will notice but will not be able to mess with in a portable way. This is true of any open system. Lisp programmers are used to it. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 23:37:09 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 20:28:30 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39486; Thu 8-Jan-87 23:26:44 EST Date: Thu, 8 Jan 87 23:25 EST From: David A. Moon Subject: Issues for the CLOS committee to start focussing on To: Common-Lisp-Object-System@SU-AI.ARPA Message-ID: <870108232540.9.MOON@EUPHRATES.SCRC.Symbolics.COM> The following issues need to be resolved and documented by February 4 (to allow a document to be distributed before the March X3J13 meeting). If we cannot resolve these among ourselves this month, we should put a brief explanation of the open issues into the document. That way, the document will accurately reflect our current status. We only have three weeks, so let's try to focus on the important points as much as possible and get some solid results down on paper. >>> HIGH PRIORITY Consistent terminology - names for relationships among classes - names for predefined classes & other interesting entities - describing the terminology at the front of the document - making sure the document adheres everywhere to the chosen terminology (this may have been resolved already, but we were still discussing it quite recently) Initialization protocol. (I have not yet started on this. I plan to think about it next week.) Method-combination. (I plan Friday to mail out complete documentation incorporating the results of the recent discussion) The class precedence rules, description, and algorithm. To a certain extent these are three separate issues. (Dick has been working on this, but I don't think it's resolved yet) What happens when the partial order of class precedence admits more than one total order. (Currently the document says that it is recommended to signal an error. I used to think that was a good idea, until I tried implementing it and applying it to some real-life programs. I reported on the results in a message of 22 Nov 86. I firmly believe the order has to be well-defined, not implementation-dependent, and cannot be considered an error. Depth-first tree-walk order appears to be the correct disambiguator.) We need to define quite explicitly the inheritance behavior of class options and slot options. There should be a table listing each option and showing how it inherits. >>> LOWER PRIORITY Structure of the classes for standard Common Lisp types. This means which types have corresponding classes, and what the subclass and precedence relations are. (I thought this was resolved last year but the document doesn't reflect that.) Class redefinition and change-class protocol. (I have not yet started on this) Class variables. (Discussion is ongoing, probably almost finished) with-slots interning issue. (Discussion is ongoing, probably almost finished) Minor issues about which I sent mail as document comments, and discussion doesn't seem to be continuing. (Unless there are objections, I plan to proceed assuming these are resolved, and update the documents accordingly.) >>> LOWEST PRIORITY Uninitialized slots (signal an error or return garbage?) (Discussion is ongoing, probably almost finished) Method lambda-list congruency rules. (The document says these are a first approximation. This issue is almost finished, but the rules for keywords might be wrong.) MAKE-CLASS, REMOVE-CLASS. (nothing in the document) Some of the functions in the Functions chapter don't make sense without the rest of meta-objects. Perhaps it should be reorganized into two chapters. :interface and :method-arguments options to defgeneric-options. (These are currently out, but might go back in once method-combination is fully clarified.)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 23:11:07 EST Date: 08 Jan 87 2001 PST From: Dick Gabriel Subject: Class Precedence List To: common-lisp-object-system@SAIL.STANFORD.EDU I am not necessarily trying to devise a new algorithm, but to duplicate the current one in such a way that explaining how it works is easier. I also have the goal of structuring the explanation so that the parts of the algorithm that are important correspond to easily identifiable portions of the explanation. Here are the important parts of the algorithm, presented in increasing order of importance: 1. We are embedding a partial order in a total order. 2. The important relations in the partial order are the lattice order and the local precedence orders. 3. In case the lattice and local precedence orders underspecify the total order, we use preorder treewalk order to specify it. How does Dave's and Danny's explanations match up to these strictures? Everyone's explanation states that a partial order is being embedded in a total order. Moon first: Moon's first two rules state number 2 pretty well, but they leave open the consideration of whether direct superclasses or superclasses are meant by ``a class always precedes its own superclasses.'' This doesn't matter, except that some reader might be slightly confused. We, of course, can state the meaning exactly in the document. Moon's rule 3 states: ``Duplicate classes are eliminated from the ordering; if a class appears more than once, it is placed as close to the beginning of the ordering as possible, while still obeying the other rules.'' What duplicates? Does this mean the user did (defclass foo ...) .... (defclass foo ...) That's silly. But it is an interpretation that some reader might pursue first. There are two interpretations. One is that the rule that states that a class always precedes its superclasses can introduce duplicates. Does this mean that this rule is inconsistent? The other possibility is that a treewalk is done from the class in question, call it C, to the top of the lattice, and the resulting list contains duplicates. The rest of the explanation, which is a description of a treewalk with insertions at the end of a list, seems to hint at the second possibility. The reader, puzzled, goes on to read the description of the treewalk process. He thinks that the treewalk is the primary means of establishing the order, and that the contraints in Moon's rules 1 and 2 sometimes change that order. Then he has to understand that the treewalk might have to be repeated to add classes left out. Why are they left out? Will this algorithm terminate? Many intelligent readers will not believe that the predicate that tells whether a class can be added at the end of the list being constructed can be tested efficiently (one of Knuth's students wasn't sure; he believed the algorithm did something reasonable after 15 minutes of study but could not convince himself it could run efficiently.) The impression that the treewalk is primay violates my third statement that the lattice order and local precedence orders are the primary determiners of the total order and the preorder is secondary. Danny next. Danny has three rules also. Rule 1 is: C-1) A class appears only once on the list. Hm. It couldn't be a total order is this weren't true. But extra information is always ok, and we can make this part read well in the document. His rules 2 and 3 are simply the local precedence order and lattice order rules, and well-stated. Here is his explanation of what the class precedence list is. I don't care about wording, but about what wrong impressions or incomprehensibilities will rise in the reader's mind. ``The class precedence list is a left to right, depth first linearization of the transitive closure of inheritance from the local super classes of a class. It satisfies three constraints: '' The first sentence states that the class precedence list is a linearization (total order) constructed by doing a preorder treewalk and then making sure some constraints are followed. Then he goes on to give an algorithm that does the preorder treewalk, putting classes that appear several times as far to the right as possible. This list is then edited using his rules 1, 2, and 3. This algorithm gives primacy to the preorder treewalk, and there is a question about whether the algorithm terminates - though it's actually easy to prove if the algorithm is stated clearly - and about how the error condition is computed. In my formulation, Moon's rules 1 and 2 and Danny's rules 2 and 3 are explicit and refer to direct superclasses. Topological sort is used because many people know it already, if they don't it's easy to explain and to prove correct, and it emphasizes that the local precedence order and lattice order are primary. The topological sort algorithm clearly highlights where the two problematic situations arise (loops and multiple orders), and it is easy to see how the loop (inconsistency) error is noticed. When multiple orders are possible, it shows up as a choice among a set of classes. The condition can be noted and the preorder treewalk information is appropriately applied here. The reader can see where this secondary constraint enters the picture. An explanation that depends on the mathematically known topological sort lends some credibility that the concept of the class precedence list and the algorithm for computing it are not ad hoc nightmares by a group of crazed hackers. Now, there is an interesting problem with the algorithm and explanation that I gave, which is the situation with the example: (defclass pie (apple cinnamon) ()) (defclass apple (fruit) ()) (defclass cinnamon (spice) ()) (defclass fruit () ()) (defclass spice () ()) EXAMPLE 1 This is one of Moon's examples. He states that his algorithm applied to it produces an order, but that several other orders are possible. The order his algorithm produces is: (pie apple fruit cinnamon spice) and the other two orders are: (pie apple cinnamon fruit spice) (pie apple cinnamon spice fruit) On the other hand, the example (defclass pie (apple cinnamon) ()) (defclass apple (fruit) ()) (defclass cinnamon (spice) ()) (defclass fruit (food) ()) (defclass spice (food) ()) (defclass food () ()) EXAMPLE 2 admits a single possibility by his rules, which is (pie apple fruit cinnamon spice food) Notice that the only difference between the two examples is that the first is a true tree while the second is a lattice with a join of FOOD. If we insist that the class directed acyclic graph be a lattice, there there is a least upper bound for every pair of classes, and the first example has an implicit top element. In this case the first example would admit the same result as the second. Here are pictures of the situations: EXAMPLE 1: fruit spice | | | | apple cinnamon \ / \ / \ / pie Notice that fruit and spice have no join. EXAMPLE 2: food / \ / \ fruit spice | | | | apple cinnamon \ / \ / \ / pie Here there is a join. EXAMPLE 1': T / \ / \ fruit spice | | | | apple cinnamon \ / \ / \ / pie If there was a top element, call it the class named T, the first situation would be this, which is the same as the original second situation (T is at the top where FOOD would be). The original second situation would become EXAMPLE 2': T | food / \ / \ fruit spice | | | | apple cinnamon \ / \ / \ / pie Without requiring that the class DAG be a lattice, my algorithm always produces a total order when there is one, while Moon's will produce the same one, but will admit several other possibilities. When the class DAG is further restricted to being a lattice, Moon's algorithm and mine agree (I think). So, I propose that the class DAG should be required to be a lattice, and because of that, I think, Moon's algorithm, Danny's, and mine are all the same, and I think mine is the easiest to understand. I don't claim superior skill at designing algorithms, because all I did was try to break Moon's and Danny's algorithms down into the simplist terms. I also propose that implementations be encouraged to offer a means of warning or signalling an error every time that appeal is made to the preorder. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 22:59:17 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 19:52:31 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39467; Thu 8-Jan-87 22:51:56 EST Date: Thu, 8 Jan 87 22:50 EST From: David A. Moon Subject: What's left to do To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 8 Jan 87 20:14 EST from Dick Gabriel Message-ID: <870108225044.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 08 Jan 87 1714 PST From: Dick Gabriel For the March x3j13 meeting we have a number of things left to do. It looks like you and I have both been worrying about the impending deadline. Sonya and I have been putting together a list of issues and my next message will be that list, as soon as I get it sorted into priority order. 2. Change-class. Discussion of this has stopped. Does this mean we're settled? 3. Initialization protocol. Again, discussion has stopped: are we agreed? I have not started on either of these. I'm trying to concentrate on one issue at a time, which is why I haven't yet answered some of the mail on these topics. I suspect we have a fair amount of work to do on 3.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 20:21:39 EST Date: 08 Jan 87 1714 PST From: Dick Gabriel Subject: What's left to do To: common-lisp-object-system@SAIL.STANFORD.EDU For the March x3j13 meeting we have a number of things left to do. 1. Method combination. Moon is at work on this, so we are likely in good shape. 2. Change-class. Discussion of this has stopped. Does this mean we're settled? 3. Initialization protocol. Again, discussion has stopped: are we agreed? 4. Class precedence list. I want to push my formulation of this. I'll be sending a message later today on the topic. The latest CONCEPTS file has a trial write-up of it. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 20:08:25 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 8 Jan 87 17:01:27 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 39397; Thu 8-Jan-87 20:01:01 EST Date: Thu, 8 Jan 87 19:59 EST From: David A. Moon Subject: Lexical environment of slot default initial value forms To: Common-Lisp-Object-System@SU-AI.ARPA Message-ID: <870108195956.4.MOON@EUPHRATES.SCRC.Symbolics.COM> DLW points out that we should specify in what environment default initial value forms for slots are evaluated, if/when they get evaluated. This includes both the lexical environment and the dynamic environment. Note that the lexical environment refers both to variables and to functions (and to go tags, blocks, and declarations, if someone was so untasteful as to do a non-local-go out of a default initial value form!); free variables are rare in these forms, but free functions are common. We discussed this and concluded that the lexical environment should be the lexical environment where the form originally appeared, i.e. the lexical environment in which defclass was evaluated, and the dynamic environment should be the one in effect at the time the form is evaluated. There are other suggestions, but they aren't as good. Happily, this is the same thing that CLtL (p.309) says for defstruct slot initialization forms. It can be difficult to get the correct lexical environment without any bugs and simultaneously maximize efficiency, especially when using :constructor, but I think it's more important for the language to have a clean definition. If some implementations have bugs that's their business. The good news is that most often these forms are constants, so the environments don't matter. An implementation can optimize that case easily enough.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 8 Jan 87 18:34:33 EST Received: from Salvador.ms by ArpaGateway.ms ; 08 JAN 87 13:01:43 PST Return-Path: Received: from SUMEX-AIM.STANFORD.EDU by Xerox.COM ; 08 JAN 87 12:59:49 PST Date: Thu, 8 Jan 87 12:53:49 PST From: Hiroshi "Gitchang" Okuno Subject: Re: getting OOPSLA proceedings To: duke%mwcamis@MITRE.ARPA cc: commonloops.pa@Xerox.COM In-Reply-To: <8701081759.AA29948@mitre.ARPA> Message-ID: <12269353881.74.OKUNO@SUMEX-AIM.STANFORD.EDU> The Proceedings of OOPSLA were published in November SIGPLAN Notices (vol. 21, no. 11). -------  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 8 Jan 87 15:04:28 EST Received: from Salvador.ms by ArpaGateway.ms ; 08 JAN 87 10:53:05 PST Return-Path: Received: from mitre.ARPA by Xerox.COM ; 08 JAN 87 10:49:48 PST Date: Thu, 8 Jan 87 12:59:36 est From: duke%mwcamis@mitre.ARPA Full-Name: Message-Id: <8701081759.AA29948@mitre.ARPA> Organization: The MITRE Corp., Washington, D.C. To: commonloops.pa@Xerox.COM Subject: getting OOPSLA proceedings -------- It seems that I remember seeing in recent netmail that the OOPSLA proceedings were going to be used for a special issue of some journal, perhaps ACM TOPLAS. Does anyone know about this? I may be confusing OOPSLA with the IBM OOP workshop proceedings which were partially published in October SIGPLAN. Thanks, Duke Briscoe duke@mitre.arpa  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 11:59:16 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 21:34:20 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38426; Thu 8-Jan-87 00:33:55 EST Date: Thu, 8 Jan 87 00:32 EST From: David A. Moon Subject: Re: Method Combination Proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870107-172419-6152@Xerox> Message-ID: <870108003249.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Thanks for the comments. I hope to converge on this before the end of the week. Date: 7 Jan 87 17:24 PST From: Gregor Kiczales The most significant comment I have about this is that in both of your proposals, you mention functions like MAKE-METHOD-CALL which can only be called from the body of a define-method-combination. (Moon says this explicitly, Danny just implies it). This may be overly restrictive. I think that all of these functions should take an extra argument (tentatively named the method-combination-identifier) which would allow them to be called by sub-functions of the particular method combination. The exisitence of this "method combination identifier" interacts with the arguments to the method combination since this identifier would have to be passed in somehow, and the first argument to the method combination is a natural place. The problem is that this makes the normal case more verbose. From a user point of view, the need for this "method combination identifier", which the user can't do anything with other than to pass right back to the system, doesn't seem very well motivated. As an implementor I can see why it's needed, but to the user it's just the system sticking its dirty laundry in his face. See below. It may be worth clarifying what this auxiliary information consists of. In Flavors, it is the arguments that the generic function will pass to the effective-method; more precisely, it is the lambda-list of the effective-method (called the combined-method in Flavors). This might be the same as, or derived from, the lambda-list of the generic function, but in various special cases it can be something else. The important point is that this information is needed to fill in the arguments to be passed to the method by the form returned by make-method-call. That's what it is in the 3600 implementation of Flavors. I don't think it is wise to constrain it to be exactly this in all implementations. So I could write (define-method-combination mine (generic-function id) ((methods (*))) (grovel-my-method-combination generic-function id methods)) (defun grovel-my-method-combination (generic-function id methods) .. (make-method-call id methods :operator 'foo) ..) What I had in mind was (define-method-combination mine () ((methods (*))) (grovel-my-method-combination #'make-method-call methods)) (defun grovel-my-method-combination (make-method-call methods) .. (funcall #'make-method-call methods :operator 'foo) ..) which makes the auxiliary-function case more verbose, but keeps the simple case simple. How does this strike you? There were three other possible ways to deal with it that I didn't like as well when thinking about this last year, but perhaps you would like them better. All of them allow make-method-call to be a globally-defined function, rather than a FLET function; the advantages of this are that the user doesn't have to pass a closure to the auxiliary function, and it becomes easier to bypass the define-method-combination level and go directly to the meta-object level, directly defining the method that define-method-combination would expand into. One is to pass any auxiliary information in special variables. This is how it is currently done in Flavors. The second is to pass any auxiliary information in the method objects. It's likely that the generic function suffices and any other auxiliary information can be found in slots of the generic function. (See next issue.) Finally, there is the approach of saying that it's a bad idea for make-method-call to depend on any auxiliary information. Instead, it should produce a form that just encodes its arguments in some suitable fashion. The caller of the method-combination function has to further process the returned form to make it into real executable code, by putting in the actual argument forms whose values are to be passed to the methods. I see three ways to do this; enclosing it in a LAMBDA or a LET that binds variables whose names are known to MAKE-METHOD-CALL; enclosing it in a MACROLET that defines a macro whose name is known to MAKE-METHOD-CALL; or code-walking. Flavors experience (we used to do it this way) shows that this is slower (at compile time) if you have to do this extra level of macro expansion, but I don't think it's really such a big deal. I'm almost convinced now that this is the right approach. In addition to MAKE-METHOD-CALL, there is WARN (or METHOD-COMBINATION-ERROR), which also requires auxiliary information in some form. Removing this auxiliary information seems more difficult; I don't see an analogy to the "bad idea" approach above. Any ideas about that? In any case, I agree that the issue of auxiliary functions called by method-combination functions needs to be addressed one way or another in the document; either by showing how it's done, or by asserting that it isn't allowed. --------------- In addition, I think the body of the method combination should have access to the generic function in question. It can't get it from the methods since methods can be on more than one generic function. I don't think that has been agreed to. It seems to be simpler to allow sharing of method-functions, but not sharing of method-objects. I agree that there should be a way for the body of define-method-combination to access the generic function. We have that in Flavors, but it was removed in the evolution of the CLOS proposal. It can be put back. --------------- PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an appropriate mechanism for dealing with this optimization. It may just be the name which is upsetting me, I am not sure yet. The other way to deal with this is to make it a keyword argument to make-method-call, which defaults to (eq operator 'progn). I would be happy with that; in fact I think it's what I proposed originally, but when we discussed this in Menlo Park, the change to PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT was made (I forget who proposed it and what the arguments were). Note that the simple form of DEFINE-METHOD-COMBINATION would need this keyword argument too. --------------- :qualifier-set vs. * in pattern-language etc. Moon's most recent message shows how defmethod can check the legality of the qualifiers just by calling the method-combination and seeing if it warns or errors. This is probably good enough, but it should be noted that it lacks the kind of precision of error message which Danny's :qualifier-set proposal had. On the other hand, the kind of tool which could make use of that precision of error message definitely comes under the environment category. So I guess just using the template language will be good enough. OK --------------- I also think the analogy between define-method-combination and defmacro is useful, it would probably be worth including this analogy in the spec. OK  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 8 Jan 87 11:58:59 EST Received: from Salvador.ms by ArpaGateway.ms ; 08 JAN 87 08:06:04 PST Return-Path: Received: from VAX.BBN.COM by Xerox.COM ; 08 JAN 87 08:04:18 PST Received: from bbng.arpa by VAX.BBN.COM id a019044; 8 Jan 87 10:48 EST Date: Thu, 8 Jan 87 10:52:15 EST From: DMACLAUGHLIN@bbng.ARPA Subject: Comments about PCL 12/2/86 To: dmaclaughlin@bbng.ARPA Resent-Date: Thu, 8 Jan 87 10:57:34 EST Resent-From: dmaclaug@VAX.BBN.COM Resent-To: commonloops.pa@Xerox.COM Message-ID: <870108-080604-1381@Xerox> The message of 12/4/86 about "changes to PCL on the horizon" sketched some of the changes that will be happening to PCL. I'm currently working with the 12/2/86 version of PCL and I'm not sure how well it is supposed to reflect the changes that this message implied would be happening. But I have compiled here a list of "discrepancies" that I have found, along with some comments and a possible bug. I hope this is helpful. 1) The proposed version of PCL states that no constructor function will be created unless explicitly requested. This is not true in the current version. 2) Similar to the above, the proposed version states that named predicates must be defined by hand. However, the current defclass does this for you. 3) This is picky, but in the examples where the allocation slot option is used, the value given to the option is not a keyword, i.e. the value is "class" instead of ":class." Right now you can't specify "class" as the allocation--you must use the keyword. Is this a typo, or is this really going to change? 4) I ran into a problem with the default printing method. It seems that this method performs a funcall on the slot accessor for each slot in the object, without checking to see if the slot has an accessor method defined for it, which leads to an error. Perhaps it should perform this check. I know you can get around it be defining a separate print-instance method, but I don't think it should be necessary to have to define one for every class which may have a slot with no accessor. (On the other hand, I feel that having a slot without an accessor is a little silly--why bother having the slot at all? Maybe you can enlighten me on this subject.) 5) I'm a little confused as to how the :initform option can be used. Where the initform is discussed in the message, it is stated that initial forms can be provided in two ways as shown below: (slotname
) or (slotname :initform ...) But what about the following, which is used in the examples given in the message? (slotname ...) I tried to do this and got an error. It seems that defclass expects that if you have more than two things in a slot description, you have to use :initform. I made the change to expand-defclass shown below to make this work. As an aside, can you say something like (slotname :allocation :class ...), where you specify the allocation and possibly other options but leave the initial value undefined? (defmethod expand-defclass ((metaclass class) name includes slots options) (keyword-parse ((accessor-prefix nil accessor-prefix-p)) options (when (and accessor-prefix-p (not (or (null accessor-prefix) (symbolp accessor-prefix)))) (error "The :accessor-prefix option, when specified must have either~%~ have an argument which is a symbol, or no argument at all.")) (setq slots (iterate ((slot in slots)) (collect (if (and (listp slot) (cddr slot)) (let ((initform-p (memq :initform (cdr slot)))) (if initform-p (list* (car slot) (cadr initform-p) (cdr slot)) slot)) ; (let ((initform ; (cadr (memq :initform (cdr slot))))) ; (list* (car slot) initform (cdr slot))) slot)))) `(ndefstruct (,name (:class ,(class-name metaclass)) (:include ,includes) ,@(and accessor-prefix-p `((:conc-name ,accessor-prefix))) (:generate-accessors ,(and accessor-prefix-p 'method)) ,@options) ,@slots))) -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 11:57:58 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 19:27:58 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38385; Wed 7-Jan-87 22:27:21 EST Date: Wed, 7 Jan 87 22:26 EST From: David A. Moon Subject: Re: Some invariants To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870107-181455-1005@Xerox> Message-ID: <870107222614.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 7 Jan 87 18:16 PST From: Masinter.pa@Xerox.COM (let ((x (make-instance 'foo)) (y (make-instance 'foo)) (setf (foo-slot x) 3) (setf (foo-slot y) 4) (foo-slot x)) It would be bad programming style for foo and its slot foo-slot to behave in a way that this returned something other than 3 without explicit documentation about this (fairly odd) behavior. Normally, one would expect that each value returned by calls make-instance to be independent of each other in this informal sense. As long as this is a style recommendation rather than an implementation requirement, expressing it as an "invariant" might be the wrong form of expression. Independent of the wording, do you agree with the sentiment? I agree that a foo class that caused this program to return 4 would be considered fairly odd and hard to understand. I certainly think it would be wrong for the language to make it impossible to implement such a class; I've had users plead with me that it was very important for them to be able to do this (have make-instance do interning of one sort or another). The style recommendation is fine, although it may be superfluous to put it into the standards document.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 8 Jan 87 11:57:46 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 18:41:44 PST Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 18:14:55 PST Date: 7 Jan 87 18:16 PST From: Masinter.pa@Xerox.COM Subject: Re: Some invariants In-reply-to: David A. Moon 's message of Wed, 7 Jan 87 20:56 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870107-181455-1005@Xerox> I need to be more careful with my wording, since I clearly said it wrong. First, the issue here is not one of capability (what can you do) but of style (what should you avoid doing). Secondly, the phrase I used "has no global side effects" doesn't describe what I meant, as David was quick to point out with a useful example of global side effects when setting an accessor. However, take the following program fragment: (let ((x (make-instance 'foo)) (y (make-instance 'foo)) (setf (foo-slot x) 3) (setf (foo-slot y) 4) (foo-slot x)) It would be bad programming style for foo and its slot foo-slot to behave in a way that this returned something other than 3 without explicit documentation about this (fairly odd) behavior. Normally, one would expect that each value returned by calls make-instance to be independent of each other in this informal sense. As long as this is a style recommendation rather than an implementation requirement, expressing it as an "invariant" might be the wrong form of expression. Independent of the wording, do you agree with the sentiment?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 7 Jan 87 21:03:51 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:58:21 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 38337; Wed 7-Jan-87 20:57:55 EST Date: Wed, 7 Jan 87 20:56 EST From: David A. Moon Subject: Re: Some invariants To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870107-172718-6156@Xerox> Message-ID: <870107205644.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 7 Jan 87 17:28 PST From: Masinter.pa@Xerox.COM That make-instance always creates new structure is a very useful property; for example, it means that (let ((x (make-instance 'foo))) (setf (foo-slot x) 3) x) has no global side effects. Not so. Someone might have done (defmethod-setf foo-slot :before ((foo foo)) (new-value) (push (list foo 'slot new-value) *mumble*)) Accessors are generic, and therefore can do anything.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 7 Jan 87 20:43:41 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:37:02 PST Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:27:18 PST Date: 7 Jan 87 17:28 PST From: Masinter.pa@Xerox.COM Subject: Re: Some invariants In-reply-to: Danny Bobrow 's message of 5 Jan 87 11:29 PST To: Bobrow.pa@Xerox.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870107-172718-6156@Xerox> I like (not (eq (make-instance x) (make-instance x))) I believe that "make-" in general is expected to create a non-EQ instance of a new object. The example you give (of looking up a name or ID and either retrieving the old one or creating a new one should be given a different name. This is clearly a matter of preference (i.e., we don't have to restrict make-instance for Classes to hang together), but the document we write can and should impose stylistic conventions for what makes sense if the user specializes built-in classes. That make-instance always creates new structure is a very useful property; for example, it means that (let ((x (make-instance 'foo))) (setf (foo-slot x) 3) x) has no global side effects.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 7 Jan 87 20:43:24 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:36:54 PST Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:24:19 PST Date: 7 Jan 87 17:24 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: Method Combination Proposal In-reply-to: David A. Moon 's message of Tue, 6 Jan 87 21:57 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM To: Bobrow.pa@Xerox.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870107-172419-6152@Xerox> The most significant comment I have about this is that in both of your proposals, you mention functions like MAKE-METHOD-CALL which can only be called from the body of a define-method-combination. (Moon says this explicitly, Danny just implies it). This may be overly restrictive. I think that all of these functions should take an extra argument (tentatively named the method-combination-identifier) which would allow them to be called by sub-functions of the particular method combination. The exisitence of this "method combination identifier" interacts with the arguments to the method combination since this identifier would have to be passed in somehow, and the first argument to the method combination is a natural place. In addition, I think the body of the method combination should have access to the generic function in question. It can't get it from the methods since methods can be on more than one generic function. So I could write (define-method-combination mine (generic-function id) ((all (*))) (grovel-my-method-combination generic-function id methods)) (defun grovel-my-method-combination (generic-function id methods) .. (make-method-call id methods :operator 'foo) ..) Note that even if we decide to restrict make-method-call to within the body of define-method-combination I think the body should have access to the generic function. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. I don't see that this is an appropriate mechanism for dealing with this optimization. It may just be the name which is upsetting me, I am not sure yet. :qualifier-set vs. * in pattern-language etc. Moon's most recent message shows how defmethod can check the legality of the qualifiers just by calling the method-combination and seeing if it warns or errors. This is probably good enough, but it should be noted that it lacks the kind of precision of error message which Danny's :qualifier-set proposal had. On the other hand, the kind of tool which could make use of that precision of error message definitely comes under the environment category. So I guess just using the template language will be good enough. I also think the analogy between define-method-combination and defmacro is useful, it would probably be worth including this analogy in the spec.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 7 Jan 87 20:42:57 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 7 Jan 87 17:37:08 PST Received: from Cabernet.ms by ArpaGateway.ms ; 07 JAN 87 17:30:07 PST Date: 7 Jan 87 17:31 PST From: Masinter.pa@Xerox.COM Subject: Re: Some invariants In-reply-to: Danny Bobrow 's message of 5 Jan 87 11:29 PST To: Bobrow.pa@Xerox.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870107-173007-6160@Xerox> (class-of (make-instance x)) = x is not as useful an invariant to protect. The weaker requirement, namely (typep (make-instance x) x) only implies (subtypep (class-of (make-instance x)) x).  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 22:10:10 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Jan 87 18:59:47 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 37316; Tue 6-Jan-87 21:59:04 EST Date: Tue, 6 Jan 87 21:57 EST From: David A. Moon Subject: Re: Method Combination Proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870106-024433-4277@Xerox> Message-ID: <870106215759.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 6 Jan 87 02:44 PST From: Danny Bobrow Moon says: Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity, but in each version it gets more and more complicated. I don't think it really achieves its goal. Allow me to offer a few other criticisms, briefly: The :qualifier-set option duplicates the information in the arguments to find-methods, with a different syntax, and with a different expressive power (unless one resorts to the escape to a predicate function). But it is the escape that I expect to use, say, for allowing one to specify for example, that a qualifier is a real (realp) where one uses the numeric value to order the methods. Or to specify a qualifier is any single symbol used as a name. I had assumed this would be done in Lisp instead of a special embedded language. See example below. ; this duplicate information will be highly error-prone. One answer is to add a new possible value, :explicit, for :qualifier-set. In this case, all explicit calls to find-method will be examined to determine allowable methods. To me this seems even more complicated. The :qualifier-set syntax doesn't seem to allow a way to say anything about unqualified methods and doesn't seem to have the flexibility to deal with methods with more than one qualifier. The examples are hard to understand since the :qualifier-set syntax used in the :and example is not the same as the syntax described earlier, and because the backquotes and commas are messed up. I would be willing to look further at the language for :qualifier-set. It was there to answer the stated needs for environment information, and I didn't give it enough thought. I don't understand this reference to environment information. I have never proposed any special programming environment facilities here, other than the :description thing to control printed representation. You're probably referring to my insistence that macros that don't check their arguments, but just ignore anything they don't recognize, are bad; I think this is a language issue, not an environment issue. Bringing that general point to the specifics of define-method-combination, I feel it's important for a method-combination function to complain if there are applicable methods that it doesn't support, rather than just ignoring them. I'm not proposing that there be a warning at defmethod time, or that a smart editor tell you when you enter the function; those things might be useful, but they really are programming environment issues and probably not appropriate for the object-oriented programming standard. I'm just saying the method-combination function should complain at the time it is called (which could be run-time, when the generic function is called, but is likely to be earlier in most implementations). If I was going to do those programming environment facilities, I would try to do them by calling the method-combination function and seeing what happens, rather than by adding a new syntax to be used in the define-method-combination specifically to convey that information. This is similar to the suggestion that the best way to find out what methods are actually called is to call the method-combination function and analyze the Lisp form it returns, rather than adding a new syntax for it to return a list of methods. Implementing this would require the condition system (another proposed CL extension), or some other way to get control when the method-combination function calls WARN. (Perhaps this is a good argument for putting back the METHOD-COMBINATION-ERROR function, which my recent proposal said was unnecessary? But I still think it's better to call it WARN and let the programming environment use FLET to make it different from the regular WARN if it needs to.) Here's an example (promised above), showing how I would write a method combination function that requires the qualifiers to be positive integers and uses the qualifiers to control the order: (define-method-combination example-method-combination () ((methods (*))) ;all methods with exactly one qualifier (dolist (method methods) (unless (typep (first (method-qualifiers method)) '(integer 0 *)) (warn "Qualifier ~S of method ~S is not a positive integer" (first (method-qualifiers method)) method) (setq methods (delete method methods)))) (make-method-call (stable-sort methods #'< :key #'(lambda (method) (first (method-qualifiers method)))))) I hope this example clarifies what I'm talking about now. All the special processing is in Lisp, not in an embedded language. Indeed, this loses some declarative expressiveness, and I can't really claim that the definition of the meaning of the method qualifiers is contained entirely, or even mostly, in the second line of the definition. However, I think it makes sense for the declarative form only to deal with the easy cases, and leave the complicated cases to imperative Lisp code. The switchover seems to be natural enough. If you ask why have the declarative form at all, all proposals seem to agree (tacitly?) that simple pattern-matching against symbols is the most common case and is too verbose to write in Common Lisp. Moon says: The first part defines the meaning of the method qualifiers, while the second part defines how the methods are glued together. It's important that the definition of the method qualifiers is all in one place, and I think it's important not to mix it up with other stuff. The question is whether it is there at point of use. Why isn't it better to separate out environmental and programmatic concerns? I hope the above makes this question moot. A survey of Symbolics object-oriented code shows that the form of standard method combination with the primary methods in most-specific-last order is not needed, so the standard method combination does not need to take any arguments (another simplification relative to my earlier proposals). The same survey showed that most-specific-last order is quite useful with some kinds of method combination that invoke all the methods (rather than shadowing), specifically progn, list, append, and, and or (this list is in decreasing order of popularity). The survey also uncovered a user-defined method combination type that takes &key arguments, hence my proposal still includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS You do not show this one example, and I strongly prefer not having arguments for this form. The details of the example really aren't relevant or interesting. I was only interested in the fact that someone found &key arguments useful here. What are your arguments against parameterizing method-combination schemas? A list of method-group specifiers follows. I assume by this you mean the item noted by: ({(variable {qualifier-pattern}+ {keyword argument}*)}*) Yes. My English needs some cleaning up and clarification. Are the qualifier-patterns all lists or NIL, and hence distinguished from the keywords? Possibly-empty lists or asterisks; this was in my message. The :ORDER keyword seems weak at best. Agreed; the message said it was only a convenience and relegated it to the "advanced facilities" section, for things that could be excluded if we wanted a lean proposal rather than a comprehensive one. I don't see any way to specify to the environment that any single symbol would be an appropriate qualifier, or that a realp was OK. I hope the above example and discussion clarified this. Declarations at the head of the body are positioned directly inside of bindings created by the lambda-list, and outside of the bindings of the method-group variables. I don't understand this. What does the declaration effect -- the computation of the effective method form, or the compilation of that form itself. The former, same as in DEFMACRO. If a doc-string is present, it documents the method-combination type. Is this how we are going to do documentation. Must we always provide such strings? Didn't someone else complain about this. I've not a fan of doc-strings, but I think it's much more important to be consistent with the rest of Common Lisp than to make diddly improvements here. To my way of thinking, the syntax of DEFINE-METHOD-COMBINATION is similar to the syntax of DEFMACRO and DEFSETF. By the way, Flavors' DEFINE-METHOD-COMBINATION doesn't allow doc-strings. If I had to rank my objections, my strongest one is against the lambda list. I'd like to understand why. Next is the restrictive nature of the qualifier language (I think the escape to a predicate is crucial). I hope this is clarified now (read my next paragraph first). If not, we need to keep discussing it. Finally, is the imposition of the idiom of putting the selection of methods up front. I could live with this if the selection language (or at least the test for qualifiers) could be made stronger. How about making that form be (variable find-method-filter &key :description :order)? I feel like I might have missed the point of this suggestion. Are you saying that in place of the qualifier patterns one could put the name of a predicate, in cases where the simple pattern match language wasn't strong enough? That seems like a good idea. If you're suggesting adding a hairier pattern match language, I don't go for that. To make sure we understand each other, I'll rewrite the earlier example in these terms: (define-method-combination example-method-combination () ((methods positive-integer-qualifier-p)) (make-method-call (stable-sort methods #'< :key #'(lambda (method) (first (method-qualifiers method)))))) (defun positive-integer-qualifier-p (method-qualifiers) (and (= (list-length method-qualifiers) 1) (typep (first method-qualifiers) '(integer 0 *)))) Thus the syntax of the third subform of define-method-combination would be extended to ({ (variable {qualifier-pattern}+ {keyword argument}*) | (variable predicate-symbol {keyword argument}*) }*) Somehow MAKE-METHOD-FROM-FORM got lost. Isn't it needed in method-combination standard around the multiple-value-prog2 form? around is a list of methods, and the multiple-value-prog2 form is not. My message said that MAKE-METHOD-FROM-FORM isn't needed. Instead MAKE-METHOD-CALL is generalized to accept forms as well as methods. By the way, I find the analogies between DEFINE-METHOD-COMBINATION and DEFMACRO useful in several ways. Would it be a good idea to use that analogy in the documentation?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 17:41:23 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 14:35:29 PST Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 14:31:52 PST Date: 6 Jan 87 14:31 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: MAKE-METHOD arguments discussion In-reply-to: David A. Moon 's message of Mon, 5 Jan 87 23:31 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870106-143152-4916@Xerox> Date: Mon, 5 Jan 87 23:31 EST From: David A. Moon Oh, gross! What is the reason for wanting this? Let's not start this again. I don't think this is gross. In fact, I think it would be gross not to do it this way. The point is, that with meta-objects, it is more natural than before for the user to write code which grovels around in the data-structure of the object system (the meta-objects). In this kind of code, it is perfectly natural to want to invoke a method's function. I think it is bad modularity to push whatever slot access optimization implementations may want to do into the user's face, by tacking extra arguments onto method functions where the user can see them. Specifically, I think the way this is done in flavors (with self-mapping-table as the first argument) is bad modularity, because the user should be allowed to think that when they type: (defmethod foo ((arg0 class) arg1 arg2) (equal (si:all-args-to-this-function) (list arg0 arg1 arg2))) foo will return t. Of course this particular piece of code is not such a good example, and any example will not be portable, by my point remains valid -- implementations should hide implementation details from the user. Sure, but doesn't using method-lambda constitute blessing the function? Yes and No. Yes, in that I don't really think method lambda is necessary, and I am not a big fan of it. No in that I think method-lambda is different than what I thought you meant by blessing the function. Here are some examples which may illustrate the difference. (flet ((make-method (specs function) (make-instance 'default-method 'argument-specifiers (mapcar #'class-named specs) 'function function))) ;; example-1 ;; In this example, a previously compiled function is being used as ;; the method function of a method being added to foo. ;; This function does not expect to benefit from any optimizations ;; which might result if the compiler had known that its first ;; argument was going to be a rocket. All this function expects is ;; that it will receive one argument. (add-method 'foo (make-method '(rocket) #'previously-compiled-fn)) ;; example-2 ;; In this example, a lambda expression is being used as the method ;; function of a method being added. The person who wrote this code ;; used method-lambda as a portable way of telling the compiler that ;; this function was going to be used as the method function of a ;; method with the argument specifiers as given in the method lambda. ;; Note that method-lambda does not authorize the compiler to change ;; the argument list of the lambda, the user must still be able to ;; get their hands on the method function and call it with one argument, ;; all method-lambda authorizes the compiler to do is to compile the ;; lambda in such a way that it "is an error" to call it with an argument ;; that is not a plane. (add-method 'foo (make-method '(plane) #'(method-lambda ((p plane)) ..))) ;; example-3 ;; This is an example of what I think of as bad blessing. In this ;; example, like in example-1, the user had a previously compiled ;; function which does not need to or expect to benefit from having ;; the compiler know the class of its first argument. But, in order ;; to make the underlying implementation happy, the user must have ;; the function blessed, which may return a function with a different ;; argument list. (add-method 'foo (make-method '(blanket) (bless-us #'previously-compiled-fn))))  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 14:29:57 EST Received: from SCRC-RIVERSIDE.ARPA by SAIL.STANFORD.EDU with TCP; 6 Jan 87 11:18:49 PST Received: from EUPHRATES.SCRC.Symbolics.COM by RIVERSIDE.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 90586; Tue 6-Jan-87 14:03:01 EST Date: Tue, 6 Jan 87 14:00 EST From: David A. Moon Subject: Re: :allocation slot-option issues To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870106-014113-4241@Xerox> Message-ID: <870106140016.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 6 Jan 87 01:40 PST From: Danny Bobrow From: David A. Moon Date: 5 Jan 87 11:07 PST From: Danny Bobrow ....Specification of Inheritance None of :reader :accessor :allocation or :initialize-only (if we still have that) are inherited.... We decided at the meeting in Menlo Park that :reader and :accessor are inherited. It is difficult to see how it could be otherwise if they are defined in terms of defmethod. Of course the methods generated by :reader and :accessor are inherited, but not the features of the slot. I see, ok. If text resulting from this conversation ends up in the document, it will have to be worded more clearly, since it's easy to interpret ":reader is not inherited" as ":reader has no effect on an inheriting class". Comments on the rest of your message to follow at some later date.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 11:28:57 EST Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 6 Jan 87 08:22:26 PST Received: from ti-csl by csnet-relay.csnet id ac01368; 6 Jan 87 10:22 EST Received: from Jenner (jenner.ARPA) by tilde id AA09984; Tue, 6 Jan 87 08:56:52 cst To: Danny Bobrow Cc: Common-Lisp-Object-System@SU-AI.ARPA, Bobrow.pa@XEROX.COM Subject: Re: Some invariants Date: 6-Jan-87 07:51:45 From: Dussud%Jenner%ti-csl.csnet@RELAY.CS.NET Message-Id: Here are some possible invariants and some arguments against them. Which ones do you like? (class-of (make-instance x)) = x The class of the result of a make-instance is always the same as its argument. A make-instance message could make a more specialized version of itself, say as an environmental feature. (not (eq (make-instance x) (make-instance x))) This could usefully not be true if one of the initialization parameters was a unique identifier (UID) that was supposed to identify the object being created, and it already existed. Then the result of make-instance should be the already existing object. The arguments you give against those invariants make me think they would be true only for the default class metaclass. Thus they shouldn't be stressed too much. (eq (class-name (class-named x)) x) This seems like it should be true, unless we make it such that classes do not know their names, and the same class can have more than one name. Is this useful? We could of course have a "hint" of a name in the class for debugging purposes. This would make classes be first class anonymous things as well. I don't remember seeing CLASS-NAMED anywhere in the document, I might be wrong though. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 05:55:07 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 02:49:54 PST Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 02:44:33 PST Date: 6 Jan 87 02:44 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Method Combination Proposal In-reply-to: David A. Moon 's message of Mon, 5 Jan 87 15:34 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870106-024433-4277@Xerox> Moon says: Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity, but in each version it gets more and more complicated. I don't think it really achieves its goal. Allow me to offer a few other criticisms, briefly: The :qualifier-set option duplicates the information in the arguments to find-methods, with a different syntax, and with a different expressive power (unless one resorts to the escape to a predicate function). But it is the escape that I expect to use, say, for allowing one to specify for example, that a qualifier is a real (realp) where one uses the numeric value to order the methods. Or to specify a qualifier is any single symbol used as a name. ; this duplicate information will be highly error-prone. One answer is to add a new possible value, :explicit, for :qualifier-set. In this case, all explicit calls to find-method will be examined to determine allowable methods. The :qualifier-set syntax doesn't seem to allow a way to say anything about unqualified methods and doesn't seem to have the flexibility to deal with methods with more than one qualifier. The examples are hard to understand since the :qualifier-set syntax used in the :and example is not the same as the syntax described earlier, and because the backquotes and commas are messed up. I would be willing to look further at the language for :qualifier-set. It was there to answer the stated needs for environment information, and I didn't give it enough thought. Moon says: The first part defines the meaning of the method qualifiers, while the second part defines how the methods are glued together. It's important that the definition of the method qualifiers is all in one place, and I think it's important not to mix it up with other stuff. The question is whether it is there at point of use. Why isn't it better to separate out environmental and programmatic concerns? A survey of Symbolics object-oriented code shows that the form of standard method combination with the primary methods in most-specific-last order is not needed, so the standard method combination does not need to take any arguments (another simplification relative to my earlier proposals). The same survey showed that most-specific-last order is quite useful with some kinds of method combination that invoke all the methods (rather than shadowing), specifically progn, list, append, and, and or (this list is in decreasing order of popularity). The survey also uncovered a user-defined method combination type that takes &key arguments, hence my proposal still includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS You do not show this one example, and I strongly prefer not having arguments for this form. A list of method-group specifiers follows. I assume by this you mean the item noted by: ({(variable {qualifier-pattern}+ {keyword argument}*)}*) Are the qualifier-patterns all lists or NIL, and hence distinguished from the keywords? The :ORDER keyword seems weak at best. I don't see any way to specify to the environment that any single symbol would be an appropriate qualifier, or that a realp was OK. Declarations at the head of the body are positioned directly inside of bindings created by the lambda-list, and outside of the bindings of the method-group variables. I don't understand this. What does the declaration effect -- the computation of the effective method form, or the compilation of that form itself. If a doc-string is present, it documents the method-combination type. Is this how we are going to do documentation. Must we always provide such strings? Didn't someone else complain about this. If I had to rank my objections, my strongest one is against the lambda list. Next is the restrictive nature of the qualifier language (I think the escape to a predicate is crucial). Finally, is the imposition of the idiom of putting the selection of methods up front. I could live with this if the selection language (or at least the test for qualifiers) could be made stronger. How about making that form be (variable find-method-filter &key :description :order)? Somehow MAKE-METHOD-FROM-FORM got lost. Isn't it needed in method-combination standard around the multiple-value-prog2 form? around is a list of methods, and the multiple-value-prog2 form is not.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 05:02:12 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 01:56:26 PST Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 01:56:43 PST Date: 6 Jan 87 01:56 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Class Precedence List In-reply-to: David A. Moon 's message of Tue, 6 Jan 87 00:53 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870106-015643-4258@Xerox> The following is my message (slightly edited to emphasize the difference from an earlier (buggy) message), and the code Gregor and I produced for class precedence list. Date: 1 Dec 86 18:50 PST Sender: Bobrow.pa Subject: Re: Class precedence list To: Moon@STONY-BROOK.SCRC.Symbolics.COM Message-ID: <861201-185029-2210@Xerox> To restate the rules I think are appropriate, they are (slightly edited from my message of 20 October): The class precedence list is a left to right, depth first linearization of the transitive closure of inheritance from the local super classes of a class. It satisfies three constraints: C-1) A class appears only once on the list. C-2) The order of classes in a local supers list is preserved C-3) A class always precedes all classes in its local supers list It can be thought of as constructed as follows: 1) Walk the inheritance tree in left to right depth first order, recording all super classes in the order visited. 2) Remove duplicates, preserving the last occurrence of any class. This can be combined with step 1 without extra consing. This ensures that C-1 is satisfied. In most cases C-2 and C-3 will also be satisfied. This is true for all the examples in the Concepts document. 3) Traverse the resulting list from left to right. If for any class c1, there is a class to its right that c1 should follow, move c1 to the right of the rightmost such class. This rightmost class must be computed by recursive application of rules C-2 and C-3. (*** This recursive dependency is the difference between my earlier set of rules that Moon found buggy, and this set) In computing this recursive dependency, a dependency loop may be discovered, indicating an error. This algorithm gives a well defined order in which all internal superclasses of class-1 will precede all internal superclasses of class-2 if there is no intersection. (*** This does provide a topological sort of the type specified by RPG, with a preferred total order based on the tree walk) Examples: No intersection (DEFCLASS1 C1 ()) (DEFCLASS1 C2 ()) (DEFCLASS1 D1 (C1)) (DEFCLASS1 D2 (C2)) (DEFCLASS1 E1 (D1 D2)) After Steps 1 and 2 (E1 D1 C1 D2 C2) Simple Intersection: (DEFCLASS1 C1 (OBJECT)) (DEFCLASS1 C2 (OBJECT)) (DEFCLASS1 D1 (C1)) (DEFCLASS1 D2 (C2)) (DEFCLASS1 E1 (D1 D2)) After Steps 1 and 2 (E1 D1 C1 D2 C2 OBJECT) Moving Required: (DEFCLASS1 C1 ()) (DEFCLASS1 C2 ()) (DEFCLASS1 C3 ()) (DEFCLASS1 D1 (C1 C2)) (DEFCLASS1 D2 (C1 C3)) (DEFCLASS1 E1 (D1 D2)) After Steps 1 and 2 (E1 D1 C2 D2 C1 C3) In step 3, C2 must be moved after C1. resulting in (E1 D1 D2 C1 C2 C3) Simple Error: (DEFCLASS1 C2 ()) (DEFCLASS1 C3 ()) (DEFCLASS1 D4 (C3 C2)) (DEFCLASS1 D5 (C2)) (DEFCLASS1 D6 (C3 C2 D5 D4)) After steps 1 and 2: (D6 D5 D4 C3 C2) Now D5 needs to after C2 from D6 definition. Computing the recursive closure of the constraints on D5, we see that C2 must be after D4 from D4, and D4 must be after D5 from D6!!! Error. Complex Constraint (DEFCLASS1 E1 (C1)) (DEFCLASS1 E2 (C2)) (DEFCLASS1 E3 (C3)) (DEFCLASS1 E4 (E3 E2 E1)) (DEFCLASS1 E5 (C1 C2)) (DEFCLASS1 E6 (C2 C3)) (DEFCLASS1 E7 (E5 E6 E4)) After Steps 1 and 2 (E7 E5 E6 E4 E3 C3 E2 C2 E1 C1) In Step 3 C3 has to be after C2 from E6, and hence after C1 from E5, giving (E7 E5 E6 E4 E3 E2 C2 E1 C1 C3) Now C2 is next in the list and it moves past C1 from E5, giving (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3). Date: Tue, 2 Dec 86 16:11 PST From: Gregor.pa Subject: code for compute-class-precedence-list To: Common-Lisp-Object-System@Sail.Stanford.edu Message-ID: <861202161119.4.GREGOR@AVALON.isl.parc.xerox.com> Line-fold: no Here is the code and some examples for the latest version of compute-class-precedence-list as described by Danny yesterday. At the end are some examples. (DEFMACRO DEFCLASS1 (NAME SUPERCLASSES) `(progn (setf (get ',name 'supers) ',superclasses))) (defun compute-class-precedence-list (root) (let ((cpl ()) (must-precede-alist ())) ;; We start by computing two values. ;; CPL ;; The depth-first left-to-right up to joins walk of the supers tree. ;; MUST-PRECEDE-ALIST ;; An alist of the must-precede relations. The car of each element of the ;;; must-precede-alist is a class, the cdr is all the classes which must ;; precede that class in the CPL. ;; ;; Note that the actual walk is breadth-first, right-to-left. ;; (labels ((walk-supers (class &optional precedence) (let ((elem (assoc class must-precede-alist))) (if elem (setf (cdr elem) (union (cdr elem) precedence)) (push (cons class precedence) must-precede-alist))) (let* ((rsupers (reverse (cons class (get class 'supers)))) (precedence (cdr rsupers))) (do ((sup rsupers (cdr sup)) (pre precedence (cdr pre))) ((null pre)) (walk-supers (car sup) pre))) (unless (member class cpl) (push class cpl))) (must-move-p (element list &aux move) (dolist (must-precede (cdr (assoc element must-precede-alist))) (when (setq move (member must-precede (cdr list))) (return move)))) (find-farthest-move (element move) (let ((closure (compute-must-precedes-closure element))) (dolist (must-precede closure) (setq move (or (member must-precede move) move))) move)) (compute-must-precedes-closure (class) (let ((closure ())) (labels ((walk (element path) (when (member element path) (class-ordering-error root element path must-precede-alist)) (dolist (precede (cdr (assoc element must-precede-alist))) (pushnew precede closure) (walk precede (cons element path))))) (walk class nil) closure)))) (walk-supers root) ;Do the walk ;; For each class in the cpl, make sure that there are no classes after it which ;; should be before it. We do this by cdring down the list, making sure that for ;; each element of the list, none of its must-precedes come after it in the list. ;; If we find one, we use the transitive closure of the must-precedes (using ;; find-farthest-move) to see where the class must really be moved. We use a ;; hand-coded loop so that we can splice things in and out of the CPL as we go. (let ((tail cpl) (element nil) (move nil)) (loop (when (null tail) (return)) (setq element (car tail) move (must-move-p element tail)) (cond (move (setq move (find-farthest-move element move)) (setf (cdr move) (cons element (cdr move))) (setf (car tail) (cadr tail));OK to use Interlisp delete trick since it (setf (cdr tail) (cddr tail));will never be the last element of the list. ) (t (setq tail (cdr tail))))) (copy-list cpl))))) (defun class-ordering-error (root element path must-precede-alist) (declare (ignore root)) (setq path (cons element (reverse (member element (reverse path))))) (let ((explanations ())) (do ((tail path (cdr tail))) ((null (cdr tail))) (let ((after (cadr tail)) (before (car tail))) (if (member after (get before 'supers)) (push (format nil "~% ~A must precede ~A -- ~A is in the local supers of ~A." before after after before) explanations) (dolist (common-precede (intersection (cdr (assoc after must-precede-alist)) (cdr (assoc before must-precede-alist)))) (when (member after (member before (get common-precede 'supers))) (push (format nil "~% ~A must precede ~A -- ~A has local supers ~S." before after common-precede (get common-precede 'supers)) explanations)))))) (error "While computing the class-precedence-list for the class ~A:~%~ There is a circular constraint through the classes:~{ ~A~}.~%~ This arises because:~{~A~}" root path (reverse explanations)))) ;;;; Examples (defclass1 o ()) (defclass1 b1 (o)) (defclass1 b2 (o)) (defclass1 b3 (o)) (defclass1 b4 (o)) (defclass1 ex1-1 (b1 b3 b4)) (defclass1 ex1-2 (b2 b3)) (defclass1 example-1 (ex1-1 ex1-2)) (equal (compute-class-precedence-list 'example-1) '(EXAMPLE-1 EX1-1 B1 EX1-2 B2 B3 B4 O)) (defclass1 o ()) (defclass1 b1 (o)) (defclass1 b2 (o)) (defclass1 b3 (o)) (defclass1 ex2-1 (b1)) (defclass1 ex2-2 (b2)) (defclass1 ex2-3 (b3)) (defclass1 example-2 (ex2-1 ex2-2 ex2-3)) (equal (compute-class-precedence-list 'example-2) '(EXAMPLE-2 EX2-1 b1 EX2-2 b2 EX2-3 b3 O)) (DEFCLASS1 C1 ()) (DEFCLASS1 C2 ()) (DEFCLASS1 C3 ()) (DEFCLASS1 C4 (C1 C2)) (DEFCLASS1 C5 (C3 C2)) (DEFCLASS1 C6 (C4 C5)) (equal (compute-class-precedence-list 'c6) '(C6 C4 C1 C5 C3 C2)) (DEFCLASS1 E1 (c1)) (DEFCLASS1 E2 (c2)) (DEFCLASS1 E3 (c3)) (DEFCLASS1 E4 (E3 E2 E1)) (DEFCLASS1 E5 (c1 c2)) (DEFCLASS1 E6 (c2 c3)) (DEFCLASS1 E7 (E5 E6 E4)) (equal (compute-class-precedence-list 'e7) '(e7 e5 e6 e4 e3 e2 e1 c1 c2 c3)) (defclass1 d0 ()) (defclass1 d1 ()) (defclass1 d2 ()) (defclass1 d3 ()) (defclass1 e (d0 d1)) (defclass1 f (d1 d2 d3)) (defclass1 g (d1 d2)) (defclass1 h (d0)) (defclass1 foo (e f g h)) (equal (compute-class-precedence-list 'foo) '(foo e f g h d0 d1 d2 d3)) (DEFCLASS1 D1 ()) (DEFCLASS1 D2 ()) (DEFCLASS1 D3 ()) (DEFCLASS1 D4 (D3 D2)) (DEFCLASS1 D5 (D2)) (DEFCLASS1 D6 (D3 D2 D5 D4)) (COMPUTE-CLASS-PRECEDENCE-LIST 'D6) ;should error (defclass1 g1 ()) (defclass1 g2 ()) (defclass1 g3 ()) (defclass1 g4 ()) (defclass1 g5 (g1 g2)) (defclass1 g6 (g2 g3)) (defclass1 g7 (g3 g4)) (defclass1 g8 (g4 g5 g6 g7)) (compute-class-precedence-list 'g8) ;should error  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 04:46:12 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jan 87 01:41:15 PST Received: from Cabernet.ms by ArpaGateway.ms ; 06 JAN 87 01:41:12 PST Date: 6 Jan 87 01:40 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: :allocation slot-option issues In-reply-to: David A. Moon 's message of Tue, 6 Jan 87 00:27 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870106-014113-4241@Xerox> From: David A. Moon Date: 5 Jan 87 11:07 PST From: Danny Bobrow ....Specification of Inheritance None of :reader :accessor :allocation or :initialize-only (if we still have that) are inherited.... We decided at the meeting in Menlo Park that :reader and :accessor are inherited. It is difficult to see how it could be otherwise if they are defined in terms of defmethod. Comments on the rest of your message to follow at some later date. Of course the methods generated by :reader and :accessor are inherited, but not the features of the slot. That is (defclass foo () ((x :initform 1 :reader foo-x))) effectively generates (demethod foo-x ((obj foo)) (slot-value obj 'x)) but (defclass fie (foo) ((x :initform 2))) does not generate (defmethod foo-x ((obj fie)) (slot-value obj 'x)) although (foo-x (make-instance 'fie)) --> 2  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 6 Jan 87 04:07:30 EST Received: from Salvador.ms by ArpaGateway.ms ; 06 JAN 87 00:31:20 PST Return-Path: Received: from ucbvax.Berkeley.EDU by Xerox.COM ; 06 JAN 87 00:29:28 PST Received: by ucbvax.Berkeley.EDU (5.53/1.19) id AA25547; Tue, 6 Jan 87 00:29:34 PST Received: by eros.berkeley.edu (1.2/5.6) id AA09571; Tue, 6 Jan 87 00:30:06 pst From: ricks%eros.Berkeley.EDU@BERKELEY.EDU (Rick L Spickelmier) Message-Id: <8701060830.AA09571@eros.berkeley.edu> Date: 6 Jan 87 00:30 PST (Tuesday) To: commonloops.pa@Xerox.COM Subject: initialize method problems... The following blows up on me (pcl date - 12/2/86): (in-package 'pcl) (defclass bob () ((a 0) (b 10)) (:accessor-prefix ||)) (defclass bill () ((c 100) (d 1000)) (:accessor-prefix ||)) (defmethod initialize ((self bob) plist) (print 'bob)) (defmethod initialize ((self bill) plist) (print 'bill)) The second defmethod causes the following error: Fatal error in function |Method NO-MATCHING-METHOD Default| (signaled with ERROR). No matching method for: INITIALIZE. Control Stack Debugger Frame #17: (|Method NO-MATCHING-METHOD Default| #) Debug 1> backtrace all -- Backtrace start -- Frame #19: (UNIVERSAL-ERROR-HANDLER |Method NO-MATCHING-METHOD Default| ERROR "No matching method for: ~S." INITIALIZE) Frame #18: (ERROR "No matching method for: ~S." INITIALIZE) Frame #17: (|Method NO-MATCHING-METHOD Default| #) Frame #16: (#:G14205-I12233-I12236 # NIL) Frame #15: (MAKE #) Frame #14: (COMPILE-METHOD-1 DISCRIMINATOR METHOD INITIALIZE (BILL) (SELF PLIST) NIL) Frame #13: (WALK-METHOD-BODY (DISCRIMINATOR METHOD INITIALIZE (BILL) (SELF PLIST) NIL) INITIALIZE #:G7401 ((PRINT (QUOTE BILL)))) Frame #12: (|Method EXPAND-DEFMETH-INTERNAL BASIC-DISCRIMINATOR BASIC-METHOD| # # (INITIALIZE) ((SELF BILL) PLIST) ((PRINT (QUOTE BILL)))) Frame #11: (REAL-EXPAND-DEFMETH (INITIALIZE) ((SELF BILL) PLIST) ((PRINT (QUOTE BILL)))) Frame #10: (DEFMETH (DEFMETH (INITIALIZE) ((SELF BILL) PLIST) (PRINT (QUOTE BILL))) (NIL NIL NIL NIL)) Frame #9: (FUNCALL # (DEFMETH (INITIALIZE) ((SELF BILL) PLIST) (PRINT (QUOTE BILL))) (NIL NIL NIL NIL)) Frame #8: (SYSTEM::%MACROEXPAND-1 (DEFMETH (INITIALIZE) ((SELF BILL) PLIST) (PRINT (QUOTE BILL))) (NIL NIL NIL NIL)) Frame #7: (SYSTEM::%MACROEXPAND (DEFMETH (INITIALIZE) ((SELF BILL) PLIST) (PRINT (QUOTE BILL))) (NIL NIL NIL NIL)) Frame #6: (SYSTEM::%EVAL (DEFMETHOD INITIALIZE ((SELF BILL) PLIST) (PRINT (QUOTE BILL)))) Frame #5: (EVAL (DEFMETHOD INITIALIZE ((SELF BILL) PLIST) (PRINT (QUOTE BILL)))) This used to work (with defclass replaced by ndefstruct), am I doing something wrong, or is my VAXLISP PCL warped.... Rick Spickelmier UC Berkeley  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 6 Jan 87 01:13:21 EST Received: from Salvador.ms by ArpaGateway.ms ; 05 JAN 87 21:34:23 PST Return-Path: Received: from ucbvax.Berkeley.EDU by Xerox.COM ; 05 JAN 87 21:32:43 PST Received: by ucbvax.Berkeley.EDU (5.53/1.19) id AA23272; Mon, 5 Jan 87 21:32:46 PST Received: by shambhala.berkeley.edu (1.2/5.6) id AA00184; Mon, 5 Jan 87 21:29:16 pst From: ricks%shambhala.Berkeley.EDU@BERKELEY.EDU (Rick L Spickelmier) Message-Id: <8701060529.AA00184@shambhala.berkeley.edu> Date: 5 Jan 87 21:29 PST (Monday) To: commonloops.pa@Xerox.COM Subject: Re: metaclass compatibility In-Reply-To: Your message of 5 Jan 87 15:26 PST (Monday). <8701052326.AA01787@shambhala.berkeley.edu> Whoops! My mistake, should have put a 'pcl::' in front of 'check-super-metaclass-compatibility', i.e. (defmethod pcl::check-super-metaclass-compatibility ((class class) (super class-of-one)) (declare (ignore class super)) t) or (import 'pcl::check-super-metaclass-compatibility) Rick Spickelmier UC Berkeley  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 01:00:32 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 21:54:44 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36292; Tue 6-Jan-87 00:54:17 EST Date: Tue, 6 Jan 87 00:53 EST From: David A. Moon Subject: Class Precedence List To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 3 Jan 87 01:31 EST from Dick Gabriel References: <861122002029.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <870106005305.4.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 02 Jan 87 2231 PST From: Dick Gabriel I've been searching for a way to explain the class precedence list computation that is simpler than the existing explanations. I think we can explain it fairly well if we relax, a bit, the requirements of implementations, though we can certainly recommend that implementations go the extra distance. What I'm proposing is a subset of the behavior that the Moon algorithm has, but it is simple to explain and understand. I'm not thrilled with any "standard" where it is legal for different implementations to produce different results for the class precedence list. That could lead to needlessly obscure portability problems. (I think Dick changed his mind on this, judging by a later message, but I'd like to get explicit confirmation in case I'm jumping to conclusions.) ....If D is a direct superclass of C, where C is in CL, then (C,D) is in the partial order. If D1 and D2 are direct superclasses of C, where C is in CL, such that D1 precedes D2 in the local precedence order, then (D1,D2) is in the partial order. (Note, these correspond to Moon's rules 1 and 2, but we explicitly list the pairs of relations, and we deal with direct superclasses only.) These are identical to "my" rules 1 and 2. If you thought those rules didn't apply to direct superclasses only, then you were misled by the inconsistent terminology in the concepts document (or by applying one terminology while reading a version of it that was written with a different terminology). Now we topologically sort the elements of CL. This is done as follows. Select a class C that is not preceded by any other. Put it first in the order. Remove C from CL and remove all pairs that mention it. This new CL is again partially ordered by the new pairs. Select a C that is not preceded by any other and put it next in the order. Continue until CL is empty. This is a fairly good description of the Lisp code I mailed out some months ago, except that it prefers treewalk order when it has a choice, rather than making an arbitrary choice. I can mail it out again if you like. If there are several total orders, the result of the topological sort depends on the order that the algorithm selects classes that are not preceded by any others. This depends, generally, on the order that the DEFCLASS's were evaluated. I propose that we require implementations to select a total order using an implementation of topological sort, and that we encourage implementations to signal an error when several total orders are possible. The referenced message (sent 22 Nov 86) was a discussion of why this (signal an error when several orders are possible) won't work. Until I did that research I had thought it was a good idea. I don't see any harm in mentioning the concept of topological sort in the documentation of how the precedence list is computed, although when we were writing the Flavors documentation we decided that it obscured more than it clarified. Perhaps you feel the CLOS standards document is aimed at a more mathematically sophisticated audience. [from a later message from Dick] I believe that this algorithm produces the same results as the New Flavors algorithm, but it is easier to explain: 1. Compute the partial order relations; 2. topologically sort; 3. when topological sort has a choice of several classes to put next, select according to preorder. That sounds identical to the so-called New Flavors algorithm to me. Is this just an issue of the particular words used to describe it, or is there something more going on that hasn't penetrated my head yet? Danny: I may have missed your last message on the subject, since I only remember messages containing algorithms that didn't work. Could you send me a message reference or at least a date? (then I can retrieve your message from one of the mailing list archives).  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 6 Jan 87 00:35:45 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 21:29:30 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36285; Tue 6-Jan-87 00:28:25 EST Date: Tue, 6 Jan 87 00:27 EST From: David A. Moon Subject: Re: :allocation slot-option issues To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870105-110752-3299@Xerox> Message-ID: <870106002722.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 5 Jan 87 11:07 PST From: Danny Bobrow ....Specification of Inheritance None of :reader :accessor :allocation or :initialize-only (if we still have that) are inherited.... We decided at the meeting in Menlo Park that :reader and :accessor are inherited. It is difficult to see how it could be otherwise if they are defined in terms of defmethod. Comments on the rest of your message to follow at some later date.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 23:40:13 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 20:33:26 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 36257; Mon 5-Jan-87 23:32:55 EST Date: Mon, 5 Jan 87 23:31 EST From: David A. Moon Subject: Re: MAKE-METHOD arguments discussion To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870105-130616-3564@Xerox> Message-ID: <870105233151.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 5 Jan 87 13:06 PST From: Gregor Kiczales Moon says: I forgot to mention that I don't see how the capability of WITH-SLOTS to determine the class of an instance-form by looking at the defmethod lambda-list can be implemented without blessing the function. Or is that a feature that only works inside defmethod and isn't available to users making their own methods at the make-method level? The reason I don't want the function to be blessed is that given this situation: (defclass foo () (x)) (defmethod foo ((f foo)) (slot-value f 'x)) I want it to be legal to say one of: (funcall (get-method (symbol-function 'foo) () (list (class-named 'foo))) (make-instance 'foo)) or: (funcall (method-function (get-method (symbol-function 'foo) () (list (class-named 'foo)))) (make-instance 'foo)) I want it to have the same effect as saying: (foo (make-instance 'foo)) Oh, gross! What is the reason for wanting this? Danny's idea for communicating class informat to with-slots, (including information which would allow optimizations), was to have method-lambda, so: (funcall #'(method-lambda ((f foo)) (with (f) x)) (make-instance 'foo 'x 1)) would return 1, but (funcall #'(method-lambda ((f foo)) (with (f) x)) nil) is an error Sure, but doesn't using method-lambda constitute blessing the function?  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 5 Jan 87 19:47:34 EST Received: from Salvador.ms by ArpaGateway.ms ; 05 JAN 87 15:30:56 PST Return-Path: Received: from ucbvax.Berkeley.EDU by Xerox.COM ; 05 JAN 87 15:29:33 PST Received: by ucbvax.Berkeley.EDU (5.53/1.19) id AA17946; Mon, 5 Jan 87 15:29:37 PST Received: by shambhala.berkeley.edu (1.2/5.6) id AA01787; Mon, 5 Jan 87 15:26:23 pst From: ricks%shambhala.Berkeley.EDU@BERKELEY.EDU (Rick L Spickelmier) Message-Id: <8701052326.AA01787@shambhala.berkeley.edu> Date: 5 Jan 87 15:26 PST (Monday) To: commonloops.pa@Xerox.COM Subject: metaclass compatibility The following gives me an incompatible metaclass error. Have I done something wrong... (or maybe my VAXLISP PCL is warped...) (use-package 'pcl) (defclass class-of-one (class) ()) (defmethod check-super-metaclass-compatibility ((class class) (super class-of-one)) (declare (ignore class super)) t) (defmethod check-super-metaclass-compatibility ((super class-of-one) (class class)) (declare (ignore super class)) t) (defclass status () ((errors 0)) (:metaclass class-of-one) (:accessor-prefix))  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 5 Jan 87 18:15:51 EST Received: from Salvador.ms by ArpaGateway.ms ; 05 JAN 87 14:26:27 PST Return-Path: Received: from GE-CRD.ARPA by Xerox.COM ; 05 JAN 87 14:23:34 PST Date: 5 Jan 87 17:22 EST From: HARRIS RICHARD M Subject: pcl in release 7 To: commonloops.pa@Xerox.COM Message-ID: <870105-142627-3705@Xerox>  Date: 5-JAN-1987 17:15 From: Rick Harris Sender: HARRISRM Subject: pcl in release 7 To: commonloops.pa@xerox.com@smtp -------- Here is a summary of the things that need to be done to make the 12/2/86 version of PCL work in release 7. 1. The feature of file attribute lists that causes a file's package to be created if it does not already exist and the package name is in parenthesis should not be used, because packages created by those definitions do not have the common lisp kind of colon mode. 2. IGNORE already has a function definition, it needs to be shadowed. (PROGN . vars) is preferable to (DECLARE (IGNORE . vars)), because the declaration will break code that uses any variable in vars. 3. 3600-low patches: compiler:defoptimizer / compiler:deftransformer deftransformers happen before macros; defoptimizers happen after macros. compiler:compile-from-stream - no need to patch this. compiler:commutative-constant-folder-recurse - definition changes from 6 to 7. 4. The release 7.0 definitions of the following functions must be fixed: define-special-form or - the macro-expander handles the last subform wrong define-special-form and - the macro-expander handles the last subform (very) wrong file-write-date - see page 13 of Genera 7.0 Issue 2 of the Software Services Technical Bulletin. define-digestable-special-form macrolet define-digestable-special-form labels define-digestable-special-form flet - Macros used in the body of these forms are expanded in the wrong environment. --------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 17:04:00 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:58:15 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:54:07 PST Date: 5 Jan 87 13:54 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: STANDARD-TYPE-CLASS In-reply-to: Dick Gabriel 's message of 31 Dec 86 15:14 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-135407-3657@Xerox> I think that the concept of built-in-class and standard-type-class as defined by Dick are important and make sense. I think these should be mixin's though since there are several possible reasonable combinations. Something like the following seems right: (defclass class () ()) ;the top (defclass built-in-class-mixin (class) ()) ;microcode knows about these (defclass standard-type-class-mixin (class) ()) ;Steele knows about these (defclass standard-class (class) ()) ;defclass makes these ;;; ;;; Important combinations of the above: ;;; (defclass standard-extensible-class (class standard-type-class-mixin) ()) (defclass standard-built-in-class (built-in-class-mixin standard-type-class-mixin) ()) The following are values that MANY, but not all implementations would return. (class-of (class-named 'pathname)) ==> standard-extensible-class (class-of (class-named 'cons)) ==> standard-built-in-class (class-of (class-named 'stream)) ==> standard-class-mixin These say that: PATHNAME is a standard class defined by Steele, in addition, it can be specified as a direct-superclass in a defclass form. FIXNUM is a standard class defined by Steele. In addition, it is represented "fundamentally" by this Lisp. STREAM is a standard class defined by Steele. It is not represented fundamentally by this Lisp, but it may not be included as a direct superclass in a defclass form.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 16:56:39 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:51:33 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:41:00 PST Date: 5 Jan 87 13:39 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: Comments on various comments In-reply-to: Masinter.pa's message of 30 Dec 86 10:52 PST To: Masinter.pa@Xerox.COM cc: Bobrow.pa@Xerox.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870105-134100-3629@Xerox> Larry says: c) (masinter) top of hierarchy is CLASS, GENERIC-FUNCTION, METHOD, with the names of the default ones unspecified, some implementations can in fact use CLASS, GENERIC-FUNCTION, METHOD and shadow any unwanted behavior in the subclasses. In another message, which I can't find, he says something like: A defclass which defined a class with no slots might create a class was an instance of no-slots-class or something. I see, I had missed an important point, which is that defclass, defmethod and friends might not always want to create the same kind of class. We might want to give them flexibility to do that. The problem is that we would definitely like people to be able to do "programmatically" what defclass, defmethod and friends do. So that SOMETHING LIKE: (setf (class-named 'foo) (make-instance 'default-class :name 'foo)) would be the same as: (defclass foo () ()) I think the easiest way to provide that ability is to specify that defclass must produce a class of class standard-class, and as I suggested before (although not with the reference to this message) we use alternative b. b) (moon) top of hierarchy is CLASS, GENERIC-FUNCTION, METHOD, with the default ones named STANDARD-CLASS, STANDARD-GENERIC-FUNCTION, STANDARD-METHOD  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 16:31:55 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:26:39 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:06:16 PST Date: 5 Jan 87 13:06 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: MAKE-METHOD arguments discussion In-reply-to: David A. Moon 's message of Sun, 28 Dec 86 19:16 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870105-130616-3564@Xerox> Moon says: I forgot to mention that I don't see how the capability of WITH-SLOTS to determine the class of an instance-form by looking at the defmethod lambda-list can be implemented without blessing the function. Or is that a feature that only works inside defmethod and isn't available to users making their own methods at the make-method level? The reason I don't want the function to be blessed is that given this situation: (defclass foo () (x)) (defmethod foo ((f foo)) (slot-value f 'x)) I want it to be legal to say one of: (funcall (get-method (symbol-function 'foo) () (list (class-named 'foo))) (make-instance 'foo)) or: (funcall (method-function (get-method (symbol-function 'foo) () (list (class-named 'foo)))) (make-instance 'foo)) I want it to have the same effect as saying: (foo (make-instance 'foo)) Danny's idea for communicating class informat to with-slots, (including information which would allow optimizations), was to have method-lambda, so: (funcall #'(method-lambda ((f foo)) (with (f) x)) (make-instance 'foo 'x 1)) would return 1, but (funcall #'(method-lambda ((f foo)) (with (f) x)) nil) is an error  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 16:31:43 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 13:26:46 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 13:14:27 PST Date: 5 Jan 87 13:14 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: Terminology: default value form In-reply-to: David A. Moon 's message of Wed, 31 Dec 86 00:50 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-131427-3572@Xerox> Moon says: "initial value form" rather than "default value form" is fine, although I don't see why users would expect this system to behave like LOOPS. It doesn't seem to have much resemblance to LOOPS. One could argue that the word "default" here is justified because this form only provides the initial value if another initial value is not specified by the caller of MAKE-INSTANCE. Thus it is the DEFAULT initial value form. Note that in the simplified initialization protocol I sent out, they are INITIAL value forms. That is because they are always evaluated by make-instance, and the slots are always set to their values. Afterwards, the initialize generic-function is called on the instance and the "init-plist". The method on initialize for OBJECT, fills in slot values from the init-plist, but some classes may override that method so they will not get this behavior.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 15:53:11 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:45:20 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 12:42:50 PST Date: 5 Jan 87 12:42 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: Question about MAKE-METHOD Arguments In-reply-to: Dick Gabriel 's message of 28 Dec 86 16:56 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-124250-3526@Xerox> Date: 28 Dec 86 16:56 PST From: Dick Gabriel To Gregor: When you state that the same ``method could be on (sic) more than one generic function,'' does this preclude different method objects sharing the same underlying method function? That is, would it be ok to have the method object know the generic function it is part of, but not the method function (which is the meat of the method object)? Do you envision glueing method objects in a variety of generic functions? I believe that the method-function of a method should be a mutable slot. Consequently, I imagine that multiple methods could have the same function. Methods could be added to a variety of generic functions, but some method-class, generic-function-class combinations will signal an error because it will be inconsistent for that kind of method to be added to that kind of generic function.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 15:50:04 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:37:28 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35536; Mon 5-Jan-87 15:35:58 EST Date: Mon, 5 Jan 87 15:34 EST From: David A. Moon Subject: Method Combination Proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <861231-172503-1727@Xerox> Supersedes: <870105153057.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <870105153453.2.MOON@EUPHRATES.SCRC.Symbolics.COM> [Please ignore the earlier version of this message. I forgot, when writing the examples, that we had agreed back in October that it was an error to have only auxiliary methods, a difference from Flavors. This version has the examples corrected.] Danny, your letter arrived at a good time since I've been thinking about method combination again. I hope we can finish up the method combination issue this week. I think your letter can be divided into two parts: first: the explanation of the overall framework and the design rationale; second: the particular syntax of the define-method-combination macro. I agree with pretty much everything in the first part, and I think it's substantially improved over my version. I don't think the second part is as good. Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity, but in each version it gets more and more complicated. I don't think it really achieves its goal. Allow me to offer a few other criticisms, briefly: The :qualifier-set option duplicates the information in the arguments to find-methods, with a different syntax, and with a different expressive power (unless one resorts to the escape to a predicate function); this duplicate information will be highly error-prone. The :qualifier-set syntax doesn't seem to allow a way to say anything about unqualified methods and doesn't seem to have the flexibility to deal with methods with more than one qualifier. The examples are hard to understand since the :qualifier-set syntax used in the :and example is not the same as the syntax described earlier, and because the backquotes and commas are messed up. The thing about my old proposed syntax for define-method-combination that I never explained very well is the reason for dividing it into two parts. The first part defines the meaning of the method qualifiers, while the second part defines how the methods are glued together. It's important that the definition of the method qualifiers is all in one place, and I think it's important not to mix it up with other stuff. I realized last week that most of the support functions are superfluous; this allows a significant simplification of the design. A survey of Symbolics object-oriented code shows that the form of standard method combination with the primary methods in most-specific-last order is not needed, so the standard method combination does not need to take any arguments (another simplification relative to my earlier proposals). The same survey showed that most-specific-last order is quite useful with some kinds of method combination that invoke all the methods (rather than shadowing), specifically progn, list, append, and, and or (this list is in decreasing order of popularity). The survey also uncovered a user-defined method combination type that takes &key arguments, hence my proposal still includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS, even though the standard kind of method combination does not use them. Here is my revised proposal for define-method-combination syntax. This goes along with the first part of Danny's message, so I won't repeat that. Lowercase Lisp words should be understood to be in italics. (DEFINE-METHOD-COMBINATION name lambda-list [macro] ({(variable {qualifier-pattern}+ {keyword argument}*)}*) {declaration | doc-string}* {form}*) name is a symbol, usable as a name for this in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS. By convention, non-keyword, non-NIL symbols are usually used. lambda-list is an ordinary lambda-list, which receives any arguments given in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS. A list of method-group specifiers follows. These define all method qualifiers that can be used with this type of method combination. Each specifier contains a variable, one or more qualifier-patterns, and zero or more keyword options. The variable is bound to a list of methods that match at least one of the qualifier-patterns, in most-specific-first order. Keyword options are described in the advanced facilities section below. A method matches a qualifier-pattern if the method's list of qualifiers is EQUAL to the qualifier-pattern, except that the symbol * in a qualifier-pattern matches anything. Thus a qualifier-pattern can be the empty list () (which matches unqualified methods), the symbol * (which matches all methods), an undotted list, or a list that ends in a dotted pair whose cdr is * (which matches any number of additional qualifiers). Qualifier-patterns are tested in the order written, so if a method could be a member of more than one method-group, it joins only the first such group. If an applicable method does not match any qualifier-pattern, the system reports an error, or a warning, that the method is not appropriate for the kind of method-combination being used. Declarations at the head of the body are positioned directly inside of bindings created by the lambda-list, and outside of the bindings of the method-group variables. If a doc-string is present, it documents the method-combination type. The value of the last form in the body is the Lisp form that specifies how the methods are combined. Erroneous conditions detected by the body should be reported with WARN; implementations will add any necessary contextual information to the warning. It is permissible for an implementation to define the functions WARN and MAKE-METHOD-CALL by enclosing the body forms in a FLET. MAKE-METHOD-CALL method-list &key :operator :around [function] Returns a form whose car is operator (default is PROGN) and whose cdr is a list of forms that call the methods. MAKE-METHOD-CALL can only be called from the body of a DEFINE-METHOD-COMBINATION. If :around is true (default is false) and the length of method-list is greater than 1, the result is a form that calls the first method and arranges for CALL-NEXT-METHOD to reach the rest of the methods, in the order they appear in method-list. In this case :operator must not be specified. Each element of method-list can be either a method-object or a form. When a form is given, it is converted into a method (conceptually by enclosing it in a LAMBDA-expression) when necessary. If method-list is NIL, the result is NIL. If method-list contains one element and PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT of the operator has been done, the result is just a form that calls the one method, with no invocation of the operator. As a convenience, if method-list is a method-object, it is automatically converted to a one-element list of that method. There are additional keywords mentioned under "Advanced Facilities". METHOD-QUALIFIERS method [function] Returns a list of the method's qualifiers. This is particularly useful when the body forms perform additional filtering or processing of the method-group lists. For example, (setq methods (remove-duplicates methods :from-end t :key #'method-qualifiers :test #'equal)) PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT symbol [function] Tells the object system that a form (symbol form1) can be optimized to just form1. Note that if symbol is a function (rather than a special operator) the optimization is only strictly valid if form1 returns exactly one value. This is not checked. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT is intended to be called at top level and is not intended to affect the compiler. Its main purpose is to enable the optimization of using an existing method as the effective method. The object system's optimizer knows about PROGN, MULTIPLE-VALUE-PROG1, and MULTIPLE-VALUE-PROG2, as well as any operators proclaimed with PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. MULTIPLE-VALUE-PROG2 form result-form {form}* [macro] The obvious extension of MULTIPLE-VALUE-PROG1. >>> EXAMPLES: ;The default method-combination technique (define-method-combination standard () ((around (:around)) (before (:before)) (primary ()) (after (:after))) ;; Must have a primary method (unless primary (warn "A primary method is required.")) (make-method-call `(,@around (multiple-value-prog2 ,(make-method-call before) ,(make-method-call primary :around t) ,(make-method-call (reverse after)))) :around t)) (define-method-combination and () ((methods () (:and))) (make-method-call methods :operator 'and)) ;A more complete version of the preceding (define-method-combination and (&optional (order ':most-specific-first)) ((around (:around)) (primary () (:and))) ;; Process the order argument (case order (:most-specific-first) (:most-specific-last (setq primary (reverse primary))) (otherwise (warn "~S is an invalid order.~@ :most-specific-first and :most-specific-last are the possible values." order))) ;; Must have a primary method (unless primary (warn "A primary method is required.")) (make-method-call `(,@around ,(make-method-call primary :operator 'and)) :around t)) >>> SHORT FORM: (DEFINE-METHOD-COMBINATION name operator [doc-string]) [macro] Defines name as a type of method combination that produces a Lisp form (operator method-call method-call...). Operator can be the name of a function, the name of a macro, or the name of a special form. This alternate syntax of DEFINE-METHOD-COMBINATION is provided for convenience and is recognized when the second subform is a non-null symbol. By convention, name and operator are often the same symbol, but this is not required. This method-combination type recognizes unqualified methods and methods with one qualifier, the keyword symbol with the same name as name, as primary methods. It also recognizes methods with one qualifier, :around, as auxiliary methods that behave the same as :around methods in standard method combination. A method-combination type defined this way always takes one optional argument, order, defaulting to :most-specific-first. A value of :most-specific-last reverses the order of the primary methods, without affecting the order of the auxiliary methods. The last example above is, in fact, an example of the macro expansion of the short form expression (define-method-combination and and). >>> ADVANCED FACILITIES: These facilities could be included if we want a comprehensive standard, or could be omitted for the time being if we prefer a stripped-down standard. I've only included facilities whose usefulness has been demonstrated in Flavors. Keyword options for method-group specifiers in define-method-combination: :ORDER -- the argument is a form evaluating to :MOST-SPECIFIC-FIRST or :MOST-SPECIFIC-LAST. If it evaluates to any other value, the system issues a warning. This is a convenience, to avoid having to write the CASE expression seen in the last example above, and does not add any expressive power. :DESCRIPTION -- the argument is a format-string used in (APPLY #'FORMAT stream description (METHOD-QUALIFIERS method)). In most cases the description will not contain any format directives. The description should be concise (one or two words). If no description is specified, a default description is chosen based on the variable name, the qualifier patterns, and whether this method-group includes the unqualified methods. This description mechanism tells programming environment tools the meaning of method qualifiers. Additional keyword arguments for MAKE-METHOD-CALL: :ARGLIST list-of-forms Uses the specified forms as the arguments to each method instead of using the arguments to the generic function. :APPLY list-of-forms Same as :arglist except that the last form in the list evaluates to a list of arguments and the call is made with apply rather than funcall. You must not specify both :arglist and :apply. This is a bit more complicated than it seems at first, because there are three potentially different argument lists involved. (1) The arguments supplied to the generic function. (2) The arguments passed from the generic function to the methods. (3) The arguments actually received by a method. (2) differs from (1) in certain proposals for discrimination on optional arguments, such as the &generic-optional one and the :interface one. (3) differs from (2) in implememtations that have a special calling sequence for methods. The :arglist/:apply keywords for make-method-call allow you to change the (2) arguments; any implementation-dependent transformation from (2) to (3) still applies. It is not a good idea to change arguments that are used for discrimination, since this could cause a method to be called with an argument that does not match its parameter specializer. WITH-METHOD-ARGUMENT-ACCESSORS lambda-list &body body [macro] This macro is convenient when changing the arguments passed to the methods. Each parameter in lambda-list is bound to a form that accesses the corresponding method argument, and then body is executed. These accessor forms come from the hidden information mentioned above. Lambda-list must match the (2) arguments mentioned above.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 15:43:35 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:33:09 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35525; Mon 5-Jan-87 15:32:16 EST Date: Mon, 5 Jan 87 15:30 EST From: David A. Moon Subject: Method Combination Proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <861231-172503-1727@Xerox> Message-ID: <870105153057.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Danny, your letter arrived at a good time since I've been thinking about method combination again. I hope we can finish up the method combination issue this week. I think your letter can be divided into two parts: first: the explanation of the overall framework and the design rationale; second: the particular syntax of the define-method-combination macro. I agree with pretty much everything in the first part, and I think it's substantially improved over my version. I don't think the second part is as good. Looking back over the old discussion, the motivation for the find-methods scheme was stated to be simplicity, but in each version it gets more and more complicated. I don't think it really achieves its goal. Allow me to offer a few other criticisms, briefly: The :qualifier-set option duplicates the information in the arguments to find-methods, with a different syntax, and with a different expressive power (unless one resorts to the escape to a predicate function); this duplicate information will be highly error-prone. The :qualifier-set syntax doesn't seem to allow a way to say anything about unqualified methods and doesn't seem to have the flexibility to deal with methods with more than one qualifier. The examples are hard to understand since the :qualifier-set syntax used in the :and example is not the same as the syntax described earlier, and because the backquotes and commas are messed up. The thing about my old proposed syntax for define-method-combination that I never explained very well is the reason for dividing it into two parts. The first part defines the meaning of the method qualifiers, while the second part defines how the methods are glued together. It's important that the definition of the method qualifiers is all in one place, and I think it's important not to mix it up with other stuff. I realized last week that most of the support functions are superfluous; this allows a significant simplification of the design. A survey of Symbolics object-oriented code shows that the form of standard method combination with the primary methods in most-specific-last order is not needed, so the standard method combination does not need to take any arguments (another simplification relative to my earlier proposals). The same survey showed that most-specific-last order is quite useful with some kinds of method combination that invoke all the methods (rather than shadowing), specifically progn, list, append, and, and or (this list is in decreasing order of popularity). The survey also uncovered a user-defined method combination type that takes &key arguments, hence my proposal still includes arguments in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS, even though the standard kind of method combination does not use them. Here is my revised proposal for define-method-combination syntax. This goes along with the first part of Danny's message, so I won't repeat that. Lowercase Lisp words should be understood to be in italics. (DEFINE-METHOD-COMBINATION name lambda-list [macro] ({(variable {qualifier-pattern}+ {keyword argument}*)}*) {declaration | doc-string}* {form}*) name is a symbol, usable as a name for this in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS. By convention, non-keyword, non-NIL symbols are usually used. lambda-list is an ordinary lambda-list, which receives any arguments given in the :METHOD-COMBINATION option to DEFGENERIC-OPTIONS. A list of method-group specifiers follows. These define all method qualifiers that can be used with this type of method combination. Each specifier contains a variable, one or more qualifier-patterns, and zero or more keyword options. The variable is bound to a list of methods that match at least one of the qualifier-patterns, in most-specific-first order. Keyword options are described in the advanced facilities section below. A method matches a qualifier-pattern if the method's list of qualifiers is EQUAL to the qualifier-pattern, except that the symbol * in a qualifier-pattern matches anything. Thus a qualifier-pattern can be the empty list () (which matches unqualified methods), the symbol * (which matches all methods), an undotted list, or a list that ends in a dotted pair whose cdr is * (which matches any number of additional qualifiers). Qualifier-patterns are tested in the order written, so if a method could be a member of more than one method-group, it joins only the first such group. If an applicable method does not match any qualifier-pattern, the system reports an error, or a warning, that the method is not appropriate for the kind of method-combination being used. Declarations at the head of the body are positioned directly inside of bindings created by the lambda-list, and outside of the bindings of the method-group variables. If a doc-string is present, it documents the method-combination type. The value of the last form in the body is the Lisp form that specifies how the methods are combined. Erroneous conditions detected by the body should be reported with WARN; implementations will add any necessary contextual information to the warning. It is permissible for an implementation to define the functions WARN and MAKE-METHOD-CALL by enclosing the body forms in a FLET. MAKE-METHOD-CALL method-list &key :operator :around [function] Returns a form whose car is operator (default is PROGN) and whose cdr is a list of forms that call the methods. MAKE-METHOD-CALL can only be called from the body of a DEFINE-METHOD-COMBINATION. If :around is true (default is false) and the length of method-list is greater than 1, the result is a form that calls the first method and arranges for CALL-NEXT-METHOD to reach the rest of the methods, in the order they appear in method-list. In this case :operator must not be specified. Each element of method-list can be either a method-object or a form. When a form is given, it is converted into a method (conceptually by enclosing it in a LAMBDA-expression) when necessary. If method-list is NIL, the result is NIL. If method-list contains one element and PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT of the operator has been done, the result is just a form that calls the one method, with no invocation of the operator. As a convenience, if method-list is a method-object, it is automatically converted to a one-element list of that method. There are additional keywords mentioned under "Advanced Facilities". METHOD-QUALIFIERS method [function] Returns a list of the method's qualifiers. This is particularly useful when the body forms perform additional filtering or processing of the method-group lists. For example, (setq methods (remove-duplicates methods :from-end t :key #'method-qualifiers :test #'equal)) PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT symbol [function] Tells the object system that a form (symbol form1) can be optimized to just form1. Note that if symbol is a function (rather than a special operator) the optimization is only strictly valid if form1 returns exactly one value. This is not checked. PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT is intended to be called at top level and is not intended to affect the compiler. Its main purpose is to enable the optimization of using an existing method as the effective method. The object system's optimizer knows about PROGN, MULTIPLE-VALUE-PROG1, and MULTIPLE-VALUE-PROG2, as well as any operators proclaimed with PROCLAIM-IDENTITY-WITH-ONE-ARGUMENT. MULTIPLE-VALUE-PROG2 form result-form {form}* [macro] The obvious extension of MULTIPLE-VALUE-PROG1. >>> EXAMPLES: ;The default method-combination technique (define-method-combination standard () ((around (:around)) (before (:before)) (primary ()) (after (:after))) (make-method-call `(,@around (multiple-value-prog2 ,(make-method-call before) ,(make-method-call primary :around t) ,(make-method-call (reverse after)))) :around t)) (define-method-combination and () ((methods () (:and))) (make-method-call methods :operator 'and)) ;A more complete version of the preceding (define-method-combination and (&optional (order ':most-specific-first)) ((around (:around)) (primary () (:and))) (case order (:most-specific-first) (:most-specific-last (setq primary (reverse primary))) (otherwise (warn "~S is an invalid order.~@ :most-specific-first and :most-specific-last are the possible values." order))) (make-method-call `(,@around ,(make-method-call primary :operator 'and)) :around t)) >>> SHORT FORM: (DEFINE-METHOD-COMBINATION name operator [doc-string]) [macro] Defines name as a type of method combination that produces a Lisp form (operator method-call method-call...). Operator can be the name of a function, the name of a macro, or the name of a special form. This alternate syntax of DEFINE-METHOD-COMBINATION is provided for convenience and is recognized when the second subform is a non-null symbol. By convention, name and operator are often the same symbol, but this is not required. This method-combination type recognizes unqualified methods and methods with one qualifier, the keyword symbol with the same name as name, as primary methods. It also recognizes methods with one qualifier, :around, as auxiliary methods that behave the same as :around methods in standard method combination. A method-combination type defined this way always takes one optional argument, order, defaulting to :most-specific-first. A value of :most-specific-last reverses the order of the primary methods, without affecting the order of the auxiliary methods. The last example above is, in fact, an example of the macro expansion of the short form expression (define-method-combination and and). >>> ADVANCED FACILITIES: These facilities could be included if we want a comprehensive standard, or could be omitted for the time being if we prefer a stripped-down standard. I've only included facilities whose usefulness has been demonstrated in Flavors. Keyword options for method-group specifiers in define-method-combination: :ORDER -- the argument is a form evaluating to :MOST-SPECIFIC-FIRST or :MOST-SPECIFIC-LAST. If it evaluates to any other value, the system issues a warning. This is a convenience, to avoid having to write the CASE expression seen in the last example above, and does not add any expressive power. :DESCRIPTION -- the argument is a format-string used in (APPLY #'FORMAT stream description (METHOD-QUALIFIERS method)). In most cases the description will not contain any format directives. The description should be concise (one or two words). If no description is specified, a default description is chosen based on the variable name, the qualifier patterns, and whether this method-group includes the unqualified methods. This description mechanism tells programming environment tools the meaning of method qualifiers. Additional keyword arguments for MAKE-METHOD-CALL: :ARGLIST list-of-forms Uses the specified forms as the arguments to each method instead of using the arguments to the generic function. :APPLY list-of-forms Same as :arglist except that the last form in the list evaluates to a list of arguments and the call is made with apply rather than funcall. You must not specify both :arglist and :apply. This is a bit more complicated than it seems at first, because there are three potentially different argument lists involved. (1) The arguments supplied to the generic function. (2) The arguments passed from the generic function to the methods. (3) The arguments actually received by a method. (2) differs from (1) in certain proposals for discrimination on optional arguments, such as the &generic-optional one and the :interface one. (3) differs from (2) in implememtations that have a special calling sequence for methods. The :arglist/:apply keywords for make-method-call allow you to change the (2) arguments; any implementation-dependent transformation from (2) to (3) still applies. It is not a good idea to change arguments that are used for discrimination, since this could cause a method to be called with an argument that does not match its parameter specializer. WITH-METHOD-ARGUMENT-ACCESSORS lambda-list &body body [macro] This macro is convenient when changing the arguments passed to the methods. Each parameter in lambda-list is bound to a form that accesses the corresponding method argument, and then body is executed. These accessor forms come from the hidden information mentioned above. Lambda-list must match the (2) arguments mentioned above.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 15:21:53 EST Received: from [192.10.41.109] by SAIL.STANFORD.EDU with TCP; 5 Jan 87 12:15:50 PST Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 35630; Mon 5-Jan-87 14:57:57 EST Date: Mon, 5 Jan 87 14:59 EST From: Daniel L. Weinreb Subject: Re: Class Precedence List To: Bobrow.pa@Xerox.COM, RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870105-094804-3149@Xerox> Message-ID: <870105145929.1.DLW@CHICOPEE.SCRC.Symbolics.COM> Line-fold: No Perhaps the X3J13 people, who'll be the first diverse group to take a look at this stuff and give us feedback, will be able to provide some useful data about which explanation turns out to be easier to understand. I've found that it's sometimes hard to predict what other people will find clear or not so clear -- when you yourself have spent a lot of time on it, it gets hard to try to put yourself in the place of someone who is seeing it for the first time. So you might consider including both explanations and then asking for opinions. (I'm assuming that this can be done without a lot of further writing effort beyond what's already written -- I realize that there isn't much time to do a significant extra writing.)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 14:58:01 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:34 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:07:52 PST Date: 5 Jan 87 11:07 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: :allocation slot-option issues In-reply-to: David A. Moon 's message of Sat, 3 Jan 87 20:47 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870105-110752-3299@Xerox> It creates a new one that overrides the one that would be inherited. This is the same model as instance variables as far as I am concerned. I don't see how you can say it's the same model. With instance variables, there is no overriding of a slot that would otherwise be inherited; there is only one slot. I suppose it must all be in how you look at it, but it sure looks inconsistent to me. I like to think (talk about) the access scope of class and instance variables (whoops I should say slots): 1) There is one variable by any name accessible from an instance. 2) It is the one nearest in scope. If there is an instance variable by that name, then it is the one, else it is the one in the class of the instance or the most specific superclass of that class. This is the same kind of nesting one gets in instantiation of function calls with lexical scoping. If there is a local variable in the function, the local value in the activation is accessed, else the nested scopes containing the function definition are searched. I think the analogy with inherited classes is very strong. Another analogy is to think of classes as providing descriptions of sets, and subclasses describing instances of subsets. Then the class variables are shared abong all instances of the set. The analogy to lexical nesting for class variables is good, I found it helpful. It doesn't apply to instance variables, though, which is another way of saying the same thing as my inconsistency complaint. I think it does apply to both class and instance variables. The variables seen by an instance (and this is the critical phrase) are just those described in all the classes it inherits from. (just as the variables seen by an activiation are all of those in all scopes it inherits from). The instance sees only one varible of any name (as does an activation). Some are stored locally, and some are shared (instance variables and class variables vs local parameters and closure variables). All instances see exctly one description of any variable. The most specific description dominates (the one in the class nearest the front of the class precedence list). Thus I am proposing that we have only one :allocation option of this type :class. Following is my proposal for the inheritance. Specification of Inheritance None of :reader :accessor :allocation or :initialize-only (if we still have that) are inherited. :initform is inherited if not overridden :type is inherited, but we do not specify what the system does with it. An open question is whether inheritance here should be a union operation, or if the more specific type must always be a subtype of the inherited one. :initform is evaluated as follows 1) Exactly once for :allocation :instance at initialization time. The value is stored in the instance. 2) At most once for :allocation :dynamic, :class At first access for :dynamic and :class, unless first access is a store. The value of the initform is stored in the instance and class respectively on this first access. 3) Each time for :allocation :none An error is signalled when trying to store in a variable with allocation :none The :none option is most useful at the top of a hierarchy where one expects some subclasses to allocate storage, but on wants to write methods that can assume they can fetch a standard value. It can also be used for subtractive inheritance at some significant cost. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 14:57:10 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:55 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:37:44 PST Date: 5 Jan 87 11:37 PST Sender: Gregor.pa@Xerox.COM From: Gregor Kiczales Subject: Re: STANDARD-TYPE-CLASS In-reply-to: Danny Bobrow 's message of 5 Jan 87 09:54 PST To: Bobrow.pa@Xerox.COM cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-113744-3348@Xerox> This message addresses this issue of what to name the class currently named class, and related issues. The current proposal seems to be: There is a class named essential-class, the english phrase "X is a class" corresponds to (typep X 'essential-class). There is a class named default-class, this is the kind of class defclass produces, it is a subclass of essential-class. There is a class named built-in-class, it is a subclass of essential-class. I basically agree with this. But it seems to me that it might be a good idea to use the name class instead of essential-class for the top of the class hierarchy. This would make the english phrase "X is a class" correspond to (typep x 'class). In addition, it would remove the use of the somewhat confusing "ESSENTIAL-xxx" convention from the standard (I confess that I use it all the time, but that doesn't mean that it isn't confusing). It seems to me that whatever convention we use here will be picked up by a lot of other programs and programmers. I think that means we should actually have a convention, with a consistent set of rules which are explained in the rationale section.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 14:56:47 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 11:50:46 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 11:29:19 PST Date: 5 Jan 87 11:29 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Some invariants To: Common-Lisp-Object-System@SAIL.STANFORD.EDU cc: Bobrow.pa@Xerox.COM Message-ID: <870105-112919-3334@Xerox> Here are some possible invariants and some arguments against them. Which ones do you like? (class-of (make-instance x)) = x The class of the result of a make-instance is always the same as its argument. A make-instance message could make a more specialized version of itself, say as an environmental feature. (not (eq (make-instance x) (make-instance x))) This could usefully not be true if one of the initialization parameters was a unique identifier (UID) that was supposed to identify the object being created, and it already existed. Then the result of make-instance should be the already existing object. (eq (class-name (class-named x)) x) This seems like it should be true, unless we make it such that classes do not know their names, and the same class can have more than one name. Is this useful? We could of course have a "hint" of a name in the class for debugging purposes. This would make classes be first class anonymous things as well.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 5 Jan 87 14:11:02 EST Received: from Salvador.ms by ArpaGateway.ms ; 05 JAN 87 10:22:12 PST Return-Path: Received: from VAX.BBN.COM by Xerox.COM ; 05 JAN 87 10:19:25 PST Date: Mon, 5 Jan 87 13:15:56 EST From: Dawn MacLaughlin To: commonloops.pa@Xerox.COM Subject: OOPSLA paper Message-ID: <870105-102212-3226@Xerox> Is there yet a version of PCL which reflects the CommonLoops as outlined in the OOPSLA '86 paper? If not, when is it expected? The version we have (*pcl-system-date* = 11/11/86) seems to be inbetween the old and the new. Dawn MacLaughlin  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 13:02:11 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 09:56:45 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 09:48:04 PST Date: 5 Jan 87 09:46 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Class Precedence List In-reply-to: Dick Gabriel 's message of 02 Jan 87 22:31 PST To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-094804-3149@Xerox> I think this is simpler because many people know topological sort already, they can understand the partial order in terms of these simple pairs, and the topological sort algorithm can be explained in a paragraph. People can also easily see where the non-determinism comes in if there are several total orders. (Note that most people would know the algorithm after reading the specification of the partial order as those pairs and seeing the phrase ``now topologically sort.'') I don't believe that this is clearer than the explanation Gregor and I gave, which in about the same amount of code used by RPG, computes the data structure, computes the preferred (preorder walk) topological sort, and provides appropriate error messages. Since the usual case with multiple inheritance of independent mixins (the usual way to use them) is that multiple sorts are possbile, it seems inappropriate to warn the user of such a case. But perhaps the best way to describe things would be to take my last message on the subject, and append the topological sort explanation for those who prefer things that way. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 13:02:05 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 09:56:51 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 09:55:28 PST Date: 5 Jan 87 09:54 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: STANDARD-TYPE-CLASS In-reply-to: David A. Moon 's message of Sat, 3 Jan 87 18:27 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-095528-3156@Xerox> I agree with the conclusions Dick reached in the referenced message. After several more discussions around here, I am willing to settle for eliminating the use of the class-name "CLASS". I would call the top of the hierarchy called ESSENTIAL-CLASS, the one the user usually gets be DEFAULT-CLASS, and have the appropriate use of STANDARD-TYPE-CLASS and BUILT-IN-CLASS. My reason is the pain of the circumlocution of the phrase class CLASS, and the clearer meaning of saying that DEFAULT-CLASS provides ... I only have one thing to add, which is to make sure that we don't lose sight of the original issue that brought this up (this time), which was to clarify the explanation of such things as which classes are not valid as superclasses in a DEFCLASS form. This is less ethereal than writing programs that reason about the Lisp implementation, but not less important. I have somehow lost sight of this issue. Do you mean that BUILT-IN-CLASS can never be a superclass of anything not a BUILT-IN-CLASS? Namely BUILT-IN-CLASS is reserved for the implementer. Is that the only restriction you have in mind? danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Jan 87 12:02:56 EST Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jan 87 08:57:07 PST Received: from Cabernet.ms by ArpaGateway.ms ; 05 JAN 87 08:46:49 PST Date: 5 Jan 87 08:45 PST Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: terminology confusion: subclass, superclass In-reply-to: David A. Moon 's message of Sat, 3 Jan 87 18:59 EST To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870105-084649-3064@Xerox> Moon says: "My conclusion from all this is that we need consistent names for the six concepts mentioned above, and I'm willing to drop the component / dependent terminology in favor of completely consistent use of: xxx subclass n>=0 proper subclass n>=1 direct subclass n=1 direct superclass n=1 proper superclass n>=1 xxx superclass n>=0 I'm looking for suggestions for the word xxx. If we really can't think of anything, that word could be omitted." I agree. I sugest we use the phrases "effective subclass" and "effective superclass" where we want to emphasize the possibility of n=0, and allow "subclass" and "superclass" to mean that as well. danny  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 5 Jan 87 09:58:32 EST Received: from Salvador.ms by ArpaGateway.ms ; 05 JAN 87 06:14:31 PST Return-Path: Received: from VAX.BBN.COM by Xerox.COM ; 05 JAN 87 06:12:55 PST Date: Mon, 5 Jan 87 9:07:23 EST From: Dawn MacLaughlin To: commonloops.pa@Xerox.COM Subject: PCL in release 7.0 Message-ID: <870105-061431-2906@Xerox> Is there a version of CommonLoops that runs in Symbolics release 7.0. Our version of 11/11/86 doesn't seem to cut the mustard. Dawn MacLaughlin  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 4 Jan 87 15:56:47 EST Date: 04 Jan 87 1251 PST From: Dick Gabriel Subject: Very Dull Message About Class Precedence Lists To: common-lisp-object-system@SAIL.STANFORD.EDU For those who are actively thinking about this issue, here is a followup on my last message about topological sort. It mostly contains a bunch of runs of a slightly modified algorithm. The modifications are that it now reports when multiple orders are possible, and, when there is a choice between several classes with no predecessors, the algorithm selects the one that appear first in a preorder treewalk from the class for which the class precedence list is being computed to the top of the lattice (viewed as a tree). I believe that this algorithm produces the same results as the New Flavors algorithm, but it is easier to explain: 1. Compute the partial order relations; 2. topologically sort; 3. when topological sort has a choice of several classes to put next, select according to preorder. (init) (defclass c1 (c2 c6 c5) ()) (defclass c2 (c3 c4) ()) (defclass c3 (c5) ()) (defclass c4 (c6) ()) (defclass c5 (top) ()) (defclass c6 (top) ()) (topologically-sort 'c1) = (C1 C2 C3 C4 C6 C5 TOP) (init) (defclass c2 (c3 c4) ()) (defclass c3 (c5) ()) (defclass c4 (c6) ()) (defclass c5 (top) ()) (defclass c6 (top) ()) (topologically-sort 'c2) = (C2 C3 C5 C4 C6 TOP) Multiple orders possible (init) (defclass c1 (c3 c2) ()) (defclass c2 (c3) ()) (defclass c3 (top) ()) (topologically-sort 'c1) = Inconsistent Lattice (init) (defclass c1 (top) ()) (defclass c2 (top) ()) (defclass c3 (top) ()) (defclass c4 (c1 c2) ()) (defclass c5 (c3 c2) ()) (defclass c6 (c4 c5) ()) (topologically-sort 'c6) = (C6 C4 C1 C5 C3 C2 TOP) Multiple orders possible (init) (defclass c1 (top) ()) (defclass c2 (top) ()) (defclass c3 (top) ()) (defclass d4 (c3 c2) ()) (defclass d5 (c2) ()) (defclass d6 (c3 c2 d5 d4) ()) (topologically-sort 'd6) = Inconsistent Lattice (init) (defclass c1 (top) ()) (defclass c2 (top) ()) (defclass c3 (top) ()) (defclass e1 (c1) ()) (defclass e2 (c2) ()) (defclass e3 (c3) ()) (defclass e4 (e3 e2 e1) ()) (defclass e5 (c1 c2) ()) (defclass e6 (c2 c3) ()) (defclass e7 (e5 e6 e4) ()) (topologically-sort 'e7) = (E7 E5 E6 E4 E3 E2 E1 C1 C2 C3 TOP) (init) (defclass c1 (top) ()) (defclass c2 (top) ()) (defclass d1 (c1) ()) (defclass d2 (c2) ()) (defclass e1 (d1 d2) ()) (topologically-sort 'e1) = (E1 D1 D1 C2 C2 TOP) Multiple orders possible (init) (defclass c1 (top) ()) (defclass c2 (top) ()) (defclass c3 (top) ()) (defclass d1 (c1 c2) ()) (defclass d2 (c1 c3) ()) (defclass e1 (d1 d2) ()) (topologically-sort 'e1) = (E1 D1 D2 C1 C2 C3 TOP) Multiple orders possible (init) (defclass c2 (top) ()) (defclass c3 (top) ()) (defclass d4 (c3 c2) ()) (defclass d5 (c2) ()) (defclass d6 (c3 c2 d5 d4) ()) (topologically-sort 'd6) = Inconsistent Lattice (init) (defclass b1 (top) ()) (defclass b2 (top) ()) (defclass b3 (top) ()) (defclass b4 (top) ()) (defclass ex1-1 (b1 b3 b4) ()) (defclass ex1-2 (b2 b3) ()) (defclass example-1 (ex1-1 ex1-2) ()) (topologically-sort 'example-1) = (EXAMPLE-1 EX1-1 B1 EX1-2 B2 B3 B4 TOP) Multiple orders possible (init) (defclass b1 (top) ()) (defclass b2 (top) ()) (defclass b3 (top) ()) (defclass ex2-1 (b1) ()) (defclass ex2-2 (b2) ()) (defclass ex2-3 (b3) ()) (defclass example-2 (ex2-1 ex2-2 ex2-3) ()) (topologically-sort 'example-2) = (EXAMPLE-2 EX2-1 B1 EX2-2 B2 EX2-3 B3 TOP) Multiple orders possible (init) (defclass d0 (top) ()) (defclass d1 (top) ()) (defclass d2 (top) ()) (defclass d3 (top) ()) (defclass e (d0 d1) ()) (defclass f (d1 d2 d3) ()) (defclass g (d1 d2) ()) (defclass h (d0) ()) (defclass foo (e f g h) ()) (topologically-sort 'foo) = (FOO E F G H D0 D1 D2 D3 TOP) (init) (defclass d1 (top) ()) (defclass d2 (top) ()) (defclass d3 (top) ()) (defclass d4 (d3 d2) ()) (defclass d5 (d2) ()) (defclass d6 (d3 d2 d5 d4) ()) (topologically-sort 'd6) = Inconsistent Lattice (init) (defclass g1 (top) ()) (defclass g2 (top) ()) (defclass g3 (top) ()) (defclass g4 (top) ()) (defclass g5 (g1 g2) ()) (defclass g6 (g2 g3) ()) (defclass g7 (g3 g4) ()) (defclass g8 (g4 g5 g6 g7) ()) (topologically-sort 'g8) = Inconsistent Lattice (init) (defclass this (is much) ()) (defclass is (too) ()) (defclass much (fun!) ()) (defclass too (top) ()) (defclass fun! (top) ()) (topologically-sort 'this) = (THIS IS TOO MUCH FUN!) Multiple orders possible -rpg-  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 4 Jan 87 00:35:02 EST Received: from Salvador.ms by ArpaGateway.ms ; 03 JAN 87 20:47:17 PST Return-Path: Received: from ucbvax.Berkeley.EDU by Xerox.COM ; 03 JAN 87 20:45:41 PST Received: by ucbvax.Berkeley.EDU (5.53/1.19) id AA22550; Sat, 3 Jan 87 20:43:43 PST Received: by eros.berkeley.edu (1.2/5.6) id AA03340; Sat, 3 Jan 87 20:42:46 pst From: ricks%eros.Berkeley.EDU@BERKELEY.EDU (Rick L Spickelmier) Message-Id: <8701040442.AA03340@eros.berkeley.edu> Date: 3 Jan 87 20:42 PST (Saturday) To: commonloops.pa@Xerox.COM Subject: bug in slot parsing In the pcl of 12/2/86, you can not declare a slot to have ':allocation :none'; the code exists to use it, but 'parse-slot-description-interal' (in braid.lsp) has the following: (check-member allocation '(:class :instance :dynamic) :test #'eq :pretty-name "the :allocation option") which causes the use of ':none' to result in an 'error'. ':none' should be added to the check, then everything seems to work okay (the few examples I tried worked fine). (check-member allocation '(:class :instance :dynamic :none) :test #'eq :pretty-name "the :allocation option") Also, for completeness, the extensions for vaxlisp in the definition of *pathname-extensions* in defsys.lsp should be changed from: #+(and dec common) ("LSP . "FAS") to #+(and dec common ULTRIX) ("lsp" . "fas") #+(and dec command VMS) ("LSP" . "FAS") Rick Spickelmier UC Berkeley  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 21:38:57 EST Date: 03 Jan 87 1835 PST From: Dick Gabriel Subject: Terminology To: common-lisp-object-system@SAIL.STANFORD.EDU I've just completed a relatively careful terminology pass over the concepts file, paying close attention to superclass, direct superclass etc. The term I really miss having and which makes for a lot of wording headaches, is ``superclass or equal,'' a parallel to ``less than or equal.'' This is Moon's superclass^n, n non-negative. I believe the proper term in lattice theory is ``filter.'' That is, the class itself and all its superclasses form a filter over the set consisting of that singleton class. This is not very intuitive (plus, I might be wrong). The reason that ``superclass'' is not a misnomer as ``component'' might be is that it is abstract, meaning exactly that is it a class that is the direct ancestor of the class, or the direct ancestor of the direct ancestor, etc. That is, it is too abstract to have an intuitive meaning outside of the hierarchy (sic). -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 20:55:21 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 17:49:24 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34471; Sat 3-Jan-87 20:48:35 EST Date: Sat, 3 Jan 87 20:47 EST From: David A. Moon Subject: Re: :allocation slot-option issues To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <861231-101817-1327@Xerox> Message-ID: <870103204740.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 31 Dec 86 10:16 PST From: Danny Bobrow (1) The document currently says If the allocation type is :class, storage for the slot is allocated in the class object created by the defclass form. The value of the slot is shared by all instances of the class. Any subclass of this class will share this single slot unless the defclass form for that subclass specifies a slot of the same name. This is okay, but points up an inconsistency between instance-variables and class-variables. Repeating the slot declaration of an instance variable does not create two separate slots, but repeating the slot declaration of a class variable does. I'm sure Alan Snyder would say that we should change instance variables to do the same as class variables, but I prefer to wonder if this indicates that something about class variables is broken. This is not the same as my model. Repeating the slot declaration of a class variable does not create two separate slots accessible from any particular instance. That's true, given the qualifier "from any particular instance." It creates a new one that overrides the one that would be inherited. This is the same model as instance variables as far as I am concerned. I don't see how you can say it's the same model. With instance variables, there is no overriding of a slot that would otherwise be inherited; there is only one slot. I suppose it must all be in how you look at it, but it sure looks inconsistent to me. I like to think (talk about) the access scope of class and instance variables (whoops I should say slots): 1) There is one variable by any name accessible from an instance. 2) It is the one nearest in scope. If there is an instance variable by that name, then it is the one, else it is the one in the class of the instance or the most specific superclass of that class. This is the same kind of nesting one gets in instantiation of function calls with lexical scoping. If there is a local variable in the function, the local value in the activation is accessed, else the nested scopes containing the function definition are searched. I think the analogy with inherited classes is very strong. Another analogy is to think of classes as providing descriptions of sets, and subclasses describing instances of subsets. Then the class variables are shared abong all instances of the set. The analogy to lexical nesting for class variables is good, I found it helpful. It doesn't apply to instance variables, though, which is another way of saying the same thing as my inconsistency complaint. Several months ago I remember we discussed splitting :allocation :class into :allocation :per-class and :allocation :shared (or some names like that) to address this problem. :per-class slots get a new copy for each dependent subclass, whereas :shared slots are shared among all dependent subclasses, even if the slot declaration is repeated. I think either the discussion was before this group got started or else it quickly dropped out of sight; I can't find it in any mail archives. Can we open this issue and discuss the pros and cons of making this change? Neither of :per-class or :shared as you describe it has the semantics I mentioned. Perhaps it would be useful to have an option :this-direct-class-only (meaning the class slot was accessible only to instances of this direct class), but I find that confusing with respect to the inheritance story. :this-direct-class-only isn't the same as either of the ones I mentioned, assuming that you meant to say that it doesn't inherit at all. :per-class is inherited, but creates a new slot each time it is inherited. :shared never creates a new slot, it always inherits the same slot. It's true that neither of these has the semantics you mentioned. So we actually have four options for class variables to consider. I'll label them with the names that happen to have been used, with no implication that I think these are the right names: :this-direct-class-only -- never inherited :per-class -- inheritance never shares :class -- inheritance shares unless shadowed :shared -- inheritance always shares As I said at the beginning of this conversation, the current definition is okay with me, but I think it's inconsistent and so I have to wonder whether it's really okay; maybe it's only okay with me because I happen not to have much interest in class variables. Perhaps this issue should be combined with the one of defining precisely the inheritance behavior of all the class options and slot options, something we have never done. I'd rather someone else be the leader on that issue, since I already have plenty of work to do, but I'm willing to make a proposal on it if no one else will.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 19:06:15 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 16:00:39 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34460; Sat 3-Jan-87 18:59:51 EST Date: Sat, 3 Jan 87 18:59 EST From: David A. Moon Subject: terminology confusion: subclass, superclass To: common-lisp-object-system@SU-AI.ARPA In-Reply-To: <861228185506.1.MOON@EUPHRATES.SCRC.Symbolics.COM>, <861229-171604-2561@Xerox>, <861229-183348-2667@Xerox>, The message of 30 Dec 86 00:11 EST from Dick Gabriel , <861230-101538-2927@Xerox>, <861230-105602-300@Xerox>, The message of 30 Dec 86 15:36 EST from Dick Gabriel , <861230-131351-1097@Xerox> Message-ID: <870103185905.4.MOON@EUPHRATES.SCRC.Symbolics.COM> This message is a bit long, but I thought it was a good idea to gather all the discussion on the subject into one place. Date: Sun, 28 Dec 86 18:55 EST From: David A. Moon We need consistent terminology for distinguishing between the direct parents of a class and the transitive closure of parentage; similarly in the child direction. Right now the document sometimes uses "superclass" and "subclass" to mean only the directly related classes, and uses "component" to mean "superclass^n, 0<=n" and "dependent" to mean "subclass^n, 0<=n". In other places the document uses "superclass" to mean the transitive closure and "direct superclass" to mean the directly related classes, and similarly for "subclass" and "direct subclass". We need to be consistent about this. I believe the component/dependent terminology is clearer, because it avoids using a single word to mean two things, but other opinions are welcome. In one message of 29 Dec, RPG agreed with the components/dependents terminology but in a later message he changed his mind. I didn't save a reference to the first message, hence this note. Date: 29 Dec 86 17:15 PST From: Danny Bobrow I don't like the term component at all. It suggests a part hierarchy, and for me any inheritance goes the wrong way; that is, components inherit features from their container not the other way. For example, a car door, a component of a car, is the same color as the car (usually). Well, one could just as well say that the color of the car is determined by the color of its various parts, such as doors, fenders, etc. However, the point about the part hierarchy is well taken. Dependent is also a misleading word because of its usage wrt interface dependencies where a view of an object is a dependent on the state of the object itself. I suggest instead consistently use the term direct super(sub)class, or local super(sub)class versus the unmodified one to indicate the closure. This is okay with me as long as it is consistent. However, it seems evident from the present state of the document that it's very easy to fall into the trap of saying "superclass" when you mean "direct superclass", which can confuse the reader. It would help if we had a two-word phrase for the transitive closure, so that any time the word "superclass" stands alone we know it is ambiguous. I don't have a suggestion, but perhaps someone more mathematically inclined than I can suggest a term. Date: 29 Dec 86 18:33 PST From: Masinter.pa@Xerox.COM using subclass for transitive closure of direct subclass and superclass for transitive closure of direct superclass seems in my memory to be more prevalent at least in the Object Oriented Programming literature. That it uses a single word to mean two things is not so serious since there is a direct relationship (as opposed to just "a relationship") between the two things. To use the mathematical analogy to its fullest, "A is a subclass of B" should be allowed when A = B, and "A is a proper subclass of B" be used to describe the situation where A /= B. Date: 29 Dec 86 2111 PST From: Dick Gabriel I believe we should distinguish immediate super/subclasses from the transitive closure of those relationships. I don't believe component/dependent are appropriate for the names of the transitive closures. For the moment I will call these relations superclass, subclass, superclass*, and subclass*. Also, I will use these words as nouns to refer to objects that bear the appropriate relationships to a given class. I completely agree that the words for the relationships should also be used as nouns referring to objects of the relationships. A component is a constituent part or ingredient. A superclass* might not be a constituent part of a class, because every aspect of it is shadowed. A dependent is something that relies on or is subject to something else. Again, a dependent might not depend on the superclass*, because everything is shadowed. Why doesn't the same argument say that a superclass* isn't a "real" superclass*, because it happens that nothing is really inherited from it? Furthermore, if a new method were added to the superclass*, for a new generic function, then suddenly there would be something that was inherited and wasn't fully shadowed, so the argument is very weak. I don't think this special case gives us any guidance on how to choose terminology. ``Component'' and ``dependent'' are not related words, and many people who see the two together might not guess that one is the dual of the other. This is a fair to good argument. I think that we should use the terminology: Term in this Message = New Term superclass* = superclass superclass = direct superclass subclass* = subclass subclass = direct subclass Date: 30 Dec 86 10:15 PST From: Danny Bobrow I agree that it would be good to consistently use the terms in column New Term. Date: 30 Dec 86 10:55 PST From: Masinter.pa@Xerox.COM I agree with the New Term naming. I would like to add superclass+ = proper superclass subclass+ = proper subclass Yes, this is important. Date: 30 Dec 86 1236 PST From: Dick Gabriel Would you prefer to use the term ``proper superclass'' or would you prefer to define that a class is not a superclass of itself? Date: 30 Dec 86 13:13 PST From: Danny Bobrow I prefer to say that a class is not a superclass of itself. It's very important to have names for "superclass^n, 0<=n" and "subclass^n, 0<=n", the improper transitive closures. That was the motivation for my suggestion of "component" and "dependent", since people often feel that "superclass" must mean the same as "proper superclass". The only use of proper might come up in testing, where we use the terminology of types. (SUBTYPEP 'object 'object) and (SUBTYPEP 'class 'object) are both true. Ah, since Common Lisp already defines that "subtype" is different from "proper subtype", it makes sense for the object extension to Common Lisp to define that "subclass" is different from "proper subclass" (and ditto for "superclass"). We need a function that will take two classes and return T if the first is equal to or a subclass of the second. Should this be named SUBCLASSP? Well, it certainly can't be named SUBCLASSP if "subclass" means the same as "proper subclass", nor if "subclass" means the same as "direct subclass". This is the same as my terminological argument about Lisp TYPEP meaning the same as English "is a". I'm not actually sure whether we need that function, or can just use SUBTYPEP, but that's an independent issue. My conclusion from all this is that we need consistent names for the six concepts mentioned above, and I'm willing to drop the component / dependent terminology in favor of completely consistent use of: xxx subclass n>=0 proper subclass n>=1 direct subclass n=1 direct superclass n=1 proper superclass n>=1 xxx superclass n>=0 I'm looking for suggestions for the word xxx. If we really can't think of anything, that word could be omitted.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 18:42:15 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 15:37:46 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34456; Sat 3-Jan-87 18:36:57 EST Date: Sat, 3 Jan 87 18:36 EST From: David A. Moon Subject: Terminology: lattice To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 30 Dec 86 00:11 EST from Dick Gabriel Message-ID: <870103183609.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 29 Dec 86 2111 PST From: Dick Gabriel Moon briefly raises the issue of the term ``lattice.'' The class lattice is not simply a lattice: The local ordering of direct superclasses matters. However, the class lattice is, then, a lattice with some additional properties. A quick breeze through my MacLane and Birkoff reveals there is no existing name for what we have. I believe we can still use the term ``lattice,'' but the figures Moon mentions ought to be altered as he suggests. That's OK with me.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 18:33:28 EST Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jan 87 15:28:51 PST Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 34452; Sat 3-Jan-87 18:28:05 EST Date: Sat, 3 Jan 87 18:27 EST From: David A. Moon Subject: STANDARD-TYPE-CLASS To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 31 Dec 86 18:14 EST from Dick Gabriel Message-ID: <870103182719.2.MOON@EUPHRATES.SCRC.Symbolics.COM> I agree with the conclusions Dick reached in the referenced message. I only have one thing to add, which is to make sure that we don't lose sight of the original issue that brought this up (this time), which was to clarify the explanation of such things as which classes are not valid as superclasses in a DEFCLASS form. This is less ethereal than writing programs that reason about the Lisp implementation, but not less important.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Jan 87 01:37:28 EST Date: 02 Jan 87 2231 PST From: Dick Gabriel Subject: Class Precedence List To: common-lisp-object-system@SAIL.STANFORD.EDU This message is long because there are a lot of examples of code running at the end. I've been searching for a way to explain the class precedence list computation that is simpler than the existing explanations. I think we can explain it fairly well if we relax, a bit, the requirements of implementations, though we can certainly recommend that implementations go the extra distance. What I'm proposing is a subset of the behavior that the Moon algorithm has, but it is simple to explain and understand. Here it is. We represent a partial order as a set of pairs, (x,y), such that (x,y) indicates that x