Received: from SAIL.Stanford.EDU (TCP 1200000013) by AI.AI.MIT.EDU 5 Oct 87 13:44:37 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Oct 87 10:28:10 PDT Received: from Semillon.ms by ArpaGateway.ms ; 05 OCT 87 10:17:47 PDT Date: Mon, 5 Oct 87 10:15:47 PDT From: Ken Kahn Subject: Re: no-applicable-method In-Reply-To: <871002-135007-6157@Xerox> To: Danny Bobrow cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871005-101747-1009@Xerox> > Alternatively, no-applicable-method could search the argument list for an > element of the forwarder class to send the message to, else signal an error. > This would not make it so dependent on the first argument. This discussion of forwarders implemented using no-applicable-method is slipping between classical (first arg) forwarders and multi-method forwarders. The classical case is pretty well-understood but doesn't fit with CLOS (as responses to your first proposal pointed out). Here you are proposing that forwarding happen on the first argument which is an instance of forwarder class. What's special about the first one? Forwarding should happen only when the object is actually involved (in actor terminology -- receiving a message). The first argument which is an instance of the forwarding class may passed around only to use under extraordinary conditions (e.g. an error stream) or might be there to embed in a structure (forwarding should not happen then). Not only is it possible to start forwarding too soon, but one may miss cases in which forwarding was intended. A generic function may have a default method, or have methods that have T specifiers where the forwarders are possible. no-applicable-method may never get called. An elegant, but too expensive, solution is to define forwarders as classes as not under T. Forwarders are of limitted utility if they only work for generic functions and not for ordinary functions. CLOS correctly hides that distinction from callers. But I haven't heard anyone proposing that ordinary functions call no-applicable-method when they get wrong-type args. Another worry I have about no-applicable-method is that it's piggy backing upon what is essentially an error mechanism (no-applicable-method). This seems to be a bad idea. (I remember a lunch discussion during IJCAI-85 about forwarders and CommonLoops. Kent Pitman argued well against forwarders using such a mechanism. No-applicable-method may get called when forwarding is inappropriate (e.g. buggy code).) Finally, I think one has to be concerned with the efficiency of an implementation of forwarding where arguments are consed together, searched, spread out and several generic functions are called. References Bobrow's message of Fri, 2 Oct 87 13:50:00 PDT -- Re: no-applicable-method  Received: from SAIL.Stanford.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Oct 87 18:04:56 EDT Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 3 Oct 87 14:51:05 PDT Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP id AA13067; Sat, 3 Oct 87 17:51:29 EDT Received: by mcvax.cwi.nl; Sat, 3 Oct 87 04:19:34 +0100 (MET) Received: by inria.inria.fr; Fri, 2 Oct 87 19:29:15 +0100 (MET) Date: Fri, 2 Oct 87 19:29:15 +0100 From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe) Message-Id: <8710021829.AA13397@inria.inria.fr> To: Bobrow.pa@xerox.com, inria!inria.inria.fr!cointe@uunet.UU.NET Subject: Re: Shared/local;class/instance Cc: RPG@sail.stanford.edu, common-lisp-object-system@sail.stanford.edu Yes, i would prefer the couple shared/instance. Here is a copy of our Ijcai paper conclusion: "We propose to keep the term class variable BUT to use it for a different meaning> . A class variable becomes an instance variable of the class treated as an object. To rename the Smalltalk term class variable we suggest the term "sharedClass" variable." Pierre  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Oct 87 16:55:37 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Oct 87 13:41:46 PDT Received: from Semillon.ms by ArpaGateway.ms ; 03 OCT 87 13:26:17 PDT Date: Sat, 3 Oct 87 13:26 PDT From: Gregor.pa@Xerox.COM Subject: Re: Constructors To: David A. Moon cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871002155644.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <871003132624.4.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: Fri, 2 Oct 87 15:56 EDT From: David A. Moon Look, it's very simple. If we're going to have a way to optimize out the interpretive processing that a naive implementation of MAKE-INSTANCE has to do, and generate specialized compiled code for making instances, then we have to have some way to redo this optimization when something changes. I claim it would be terrible for programmers to have to do that by hand. I claim that constructors are a better way to keep track of this automatically than any other way, because the special processing is confined to a system generated function, and kept away from user written functions. So what are the alternatives? We can decide that we don't care about speeding up object creation that much, or someone can propose a specific, coherent alternative. I guess neither of us can figure out what the other is talking about here. Maybe my previous paragraph makes this more clear: I hope so. If not, you should respond with something very specific, such as an example showing exactly what a programmer would write to get an efficient constructor. Perhaps it should be something that has the same semantics as (defclass class1 () ((a :initarg :a) (b :initarg :b))) (defclass class2 (class1) ((c :initarg :c) table) (:default-initargs :b 1) (:constructor make-2 (a &optional n b c))) (defmethod initialize-instance :after ((x class2) &key (n 10)) (setf (slot-value x 'table) (make-array n))) (make-2 "foo" 5) I don't understand why make-2 has to be any faster at all than: (defun make-3 (a &optional n b c) (make-instance 'class2 :a a :n n :b b :c c)) And I still don't understand what other convenience is gotten from this in the way of automatically fixing stuff if one of the defclasses changes. -------  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 3 Oct 87 16:29:59 EDT Received: from Semillon.ms by ArpaGateway.ms ; 03 OCT 87 13:11:06 PDT Date: Sat, 3 Oct 87 13:08 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug To: MBM@CAF.MIT.EDU cc: CommonLoops.pa@Xerox.COM In-Reply-To: <2769195635-16374562@CHAPLIN> Message-ID: <871003130803.2.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: Fri, 2 Oct 87 17:00:35 EDT From: MBM@CAF.MIT.EDU Date: 30 Sep 87 11:10 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU Subject: Re: :accessor-prefix bug I would think that the correct Common Lisp way to deal with the question would be to handle it the same way that defstruct handles conc-name. This first proposal seems like the right way to go. Are the certain circumstances that you mention also problematic for defstruct, or are the problems unique to defclass? Has this question been answered? If so, I missed it. --mike After OOPSLA, I will send a more detailed reply to this. The short form of the answer is that the current mechanism used by defstruct has the package problems described in an earlier message. defstruct interns its constructed symbols in the package which is the value of the dynamic variable *package* at <>. This can lead to surprising results under certain not very well defined circumstances. -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Oct 87 16:16:03 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Oct 87 13:00:20 PDT Received: from Semillon.ms by ArpaGateway.ms ; 03 OCT 87 12:59:53 PDT Date: Sat, 3 Oct 87 12:59 PDT From: Gregor.pa@Xerox.COM Subject: Constructors To: David A. Moon , Danny Bobrow cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU, kempf%hplabsz@hplabs.HP.COM In-Reply-To: <870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM>, <871002-113229-5844@Xerox>, <871002145323.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <871003125948.1.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no This message contains my comments about constructors. I wrote this quickly, but I have been thinking about it for a while. This means that this may sound a little rough or confused, but I believe pretty firmly what I am trying to say. If there is a part that seems confusing give it another read. I won't be reading any more mail until after OOPSLA, so I won't be able to respond to responses to this till then. Date: Wed, 30 Sep 87 12:37 EDT From: David A. Moon This is a proposal to add constructors back into CLOS, now that the basic object creation protocol has been agreed upon. WHY HAVE CONSTRUCTORS? (1) A cleaner interface for the caller It's often appropriate to have a more abstract interface than the one provided by MAKE-INSTANCE. Providing a constructor as the documented inter-module interface for making a particular kind of object encourages users of the interface to think in more abstract, conceptual terms. Using a constructor also allows more aspects of the implementation to be changed without changing the interface: the class name and initarg names could be changed, or the data representation could be changed to a DEFSTRUCT representation or a standard-type, without changing the interface. The constructor could even be replaced by an interface function that does some complex computations to decide what type of object to create, or to decide whether to return an existing object or create a new one. It is true that sometimes, constructors present a more appropriate interface for the caller. On the other hand, it is often the case that they are not a more appropriate interface for the caller since if the caller decides to make a intance of a slightly more specialized version of something they must either define a new constructor or resort to calling make-instance. Also, I believe that much of the functionality you say can be gotten with constructors can be gotten just as well with make-instance. By using individual methods on make-instance, it would be easy for a programmer to have code that for a particular class "does some complex computations to decide what type of object to create, or to decide whether to return an existing object or create a new one". Some might argue that individual methods on make-instance are bad style, (I don't know what I think) but I believe that argument would be an equally strong argument against that kind of constructor function. Also, if we decide to do structure-class (I assume we will) the programmer could change to a defstruct and still use code that calls make-instance. Also, while it is true that these are reasonable arguments for the use of constructors as an interface to the caller, they are not arguments for why there should be a :constructor option. I understand that you go on to acknowledge that, but I wanted to make it clear. These needs could be met simply by defining constructor functions with DEFUN and advertising them. Some reasons to have a :CONSTRUCTOR option in DEFCLASS are - to make it easier and more convenient for users to create constructors As Danny says, I believe this sacrifices reading ease in favor of typing ease in a serious way. - to be culturally consistent with DEFSTRUCT I agree with Danny about this too. - :CONSTRUCTOR is a convenient abbreviation for something you could do yourself in a more long-winded way, just like :ACCESSOR Sort of, but :accessor is a more trivial case. But perhaps we should get rid of :accessor? (Later in this message I make more comments about :accessor.) Other reasons appear below. (2) Coordination with class redefinition As the bridge between an external interface and the internal structure of a class, a constructor function contains certain information about the class, such as what are its initargs and their default values. When a class is redefined, any constructors for the class and its subclasses should be updated if necessary to keep them consistent with the class. Making this updating automatic is a convenience for programmers, so they don't have to remember to do it by hand. One way to make the updating automatic would be to add a new feature to the programming environment by which a linkage could be established between a function and a class so that redefining the class makes some edits to the source of the function and then recompiles it. A much simpler way is to make the constructor syntactically part of the DEFCLASS, so it naturally gets updated at the same time as the rest of the DEFCLASS. This is another way in which constructors are analogous to accessors. I believe this is the strongest argument I have heard for constructors. But lets look at it for a minute. - Lets suppose that someone is defining boa constructors by hand (using defun). Presumably their reason for doing this is that they want to present a boa interface to a subset of the total initargs the function accepts. In that case, changes to the class lattice which affect the initargs the embedded call to make-instance accepts can have one of two effects: 1: They don't change the initargs the constructor is presenting a boa interface to. In this case the original constructor defun is more than likely still semantically and syntactically correct. 2: They do affect the initargs the constructor is presenting a boa interface to. In this case the constructor defun is going to have to be examined and perhaps edited. But in this case what would having a :constructor option to defclass have bought the user? Nothing as near as I can tell, they will still have to examine that :constructor option and perhaps edit it. The point being that in general, if there is a change which affects the initargs a constructor is providing a boa interface to the programmer is going to have to examine the constructor to make sure it is still valid. Now lets look at the case where the constructor is not providing a boa interface but rather is providing just a initarg interface like make instance. In this case the constructor looks like: (defun make-foo (&rest args) (apply #'make-instance 'foo args)) Well in this case the code defined with defun will always be valid under changes to the class lattice, only the code that actually calls make-foo can become incorrect and so once again I see no real benefit being provided by the :constructor option. (3) More efficient than MAKE-INSTANCE Gregor has argued that calls to MAKE-INSTANCE with a constant first argument can be equally optimized, since the exact class being constructed is known. While this is true in theory, it seems that either a complicated mechanism would be needed to make sure that the function was recompiled when the class was redefined in a way that invalidated the inline code, or else there would have to be user-visible declarations to control the tradeoff between performance and robustness in the face of class redefinition. Alternatively, calls to MAKE-INSTANCE with a constant first argument could be turned into calls to a constructor function that was created behind the scenes. Then if the class was redefined, only the constructor function would have to be recompiled. In either case, if we are going to have this type of mechanism, I would much rather make it explicitly visible as a :CONSTRUCTOR option than have it operating behind the scenes in some vaguely defined way. What you describe as the alternative is the only way I have thought of doing it and I don't in any way see why this is harder to implement that the mechanism you are proposing. I do believe I have show the two be be of equivalent difficulty to implement. Also, I don't really believe semantic preserving optimizations need to be made explicit. That is the opposite of what a (safe) compiler optimization means to me. Whats more, if we explicitly document that :constructors are likely to be faster than make-instance we will be encouraging users to use constructors all the time rather than make-instance and I think that would be bad bad bad. WHY GET RID OF CONSTRUCTORS? (1) Simplicity If we have both constructors and MAKE-INSTANCE, then we have two ways to do the same thing. [But CLOS very often provides both a primitive mechanism and a convenient abbreviation for a common case of using that mechanism.] The rules for mapping constructor parameter names into slots and initargs are complicated and confusing. [Very true. In this proposal they have been enormously simplified.] I must confess that the rules you propose here are simpler than those before. (2) Avoid hiding mechanisms Constructors contain a hidden performance optimization, in that there is more inlining in their bodies than can be achieved through documented mechanisms elsewhere. [I argued above that this is preferable to the inherent complexity of making that mechanism generally available. Of course there is nothing to stop us from documenting it if that's what we really want. Also, exactly the same thing could be said about :ACCESSOR, at least in the Symbolics implementation.] See my comment above about how bad it would be to explicitly say that constructors are faster than make-instance. Also note that it would be trivial to teach your implementation (and mine) to reckognize the following and optimize it the same way as accessors: (defmethod foo-x ((foo foo)) (slot-value foo 'x)) (3) Not more efficient than MAKE-INSTANCE (see discussion above) I have read carefully the rest of the message which contains the details of the proposal, but am not going to comment on those details here other than to say that as a proposal for constructors they seem reasonable. Summary: I am still opposed to adding constructors to CLOS. I do believe that they will make life a little more convenient for some programmers, but I don't think those advantages outweigh the conceptual problems I outline above nor do I think they are worth the added complexity of having to describe and understand how they work and documenting the mechanism which is used to compile them and cause them to get recompiled when appropriate. -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 3 Oct 87 15:02:59 EDT Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 3 Oct 87 11:49:18 PDT Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP id AA10829; Sat, 3 Oct 87 14:49:43 EDT Received: by mcvax.cwi.nl; Sat, 3 Oct 87 04:11:25 +0100 (MET) Received: by inria.inria.fr; Fri, 2 Oct 87 19:22:53 +0100 (MET) Date: Fri, 2 Oct 87 19:22:53 +0100 From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe) Message-Id: <8710021822.AA13243@inria.inria.fr> To: Bobrow.pa@xerox.com, inria!inria.inria.fr!cointe@uunet.UU.NET Subject: Re: Shared/local;class/instance Cc: RPG@sail.stanford.edu, common-lisp-object-system@sail.stanford.edu Yes i would prefer shared/insatance... (if fact that is exactly our proposal (briot and me) descriebed in our last Ijcai paper). Pierre  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 19:55:40 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 16:40:11 PDT Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 16:38:07 PDT Date: Fri, 2 Oct 87 16:37 PDT From: Gregor.pa@Xerox.COM Subject: fixing our problems with setf To: David A. Moon , Patrick H Dussud cc: Common-Lisp-Object-System@Sail.Stanford.edu, Gregor.pa@Xerox.COM In-Reply-To: <870921163510.2.MOON@EUPHRATES.SCRC.Symbolics.COM>, <2768308570-8410382@Jenner>, <870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM>, <870921200005.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <871002163721.4.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no As I believe I made clear before, I believe Common Lisp would be a better language if setf facility it provided was a lot simpler. This message starts by making more clear what it is I think would have been a better original design, it then goes on to propose a clean up of setf which has many of the same nice properties but is compatible with the current situation. In my 'improved original design' the setf mechanism would just be an abbreviation for calling a function whose name was (SETF -symbol-). There would be no defsetf or any other mechanism for changing the way the setf macro would expand under certain circumstances. Here is an example of how this would work: (setq mex (macroexpand '(setf (foo 1 2) 3))) (LET ((#:G0 1) (#:G1 2) (#:G2 3)) (FUNCALL #'(SETF FOO) #:G2 #:G0 #:G1)) ;;; ;;; at this point, assuming there was no previous definition for ;;; (setf foo) attempting to evaluate the form bound to MEX would ;;; signal an error. ;;; (eval mex) >Error: undefined function (SETF FOO)... ;;; ;;; but if we define a function (SETF FOO) then eval of mex would work ;;; as expected (defun (setf foo) (new-value indicator) ...) What are the features of this mechanism: The macroexpansion of setf does not depend on any defining form, lexical environment, compile environment or anything. Because it is not possible to do a 'top-level' definition for setf expansion, there are no problems with wanting to do a lexical binding of a rule for setf expansion. Also because the expansion of setf does not depend on the argument list of FOO or (SETF FOO), there can't be any problems with having to re-expand (recompile) code after the defun for foo or (setf foo) changes. This rule for setf always puts the new value argument as the first of the other arguments, this rule always works since it doesn't depend on the definition of FOO or (SETF FOO). Of course, proposing to Common Lisp that they completely do away with defsetf is probably too radical a proposal. But I believe there is a useful intermediate ground which could help us all. 1) Change the behavior of setf so that in the absence of any special information provided by defsetf it expands as shown above. 2) Add the setf function spec to the language to support this. But note that the forms like defun and defmethod would only have one lambda-list. The programmer would know that the function/method will be receiving the new-value as its first argument. 3) Document very clearly that this is the suggested way of using setf and that the only real reason to continue using the old form of setf is to do things like LDB or other fundamentally macro-ish things. I believe this proposal solves many of the problems previously raised in a clean simple way: Date: Tue, 22 Sep 87 09:36:10 CDT From: Patrick H Dussud The problem is that we can't always specialize on the new-value argument using the short defsetf form. The programmer will have to write a hocky defsetf form to get around the problem of having optional arguments (e.g. implementing the setf form of SUBSEQ as a generic function). We lose the COMBINE-LAMBDA-LISTS abstraction. In this scheme we can always specialize on the new value form since the programmer can count on it coming in as the first argument to the setf function. Date: Mon, 28 Sep 87 16:55 EDT From: David A. Moon The next issue is what to do about the lambda-list of a setf-function. We already agreed on what is the lambda-list in the expansion of (defun (setf foo) ...) into (setf (symbol-function '(setf foo)) #'(lambda ...)). Specifically, #'(setf foo) takes one more required argument than #'foo, and the last required argument is the new value to be stored. The issue is whether certain function-defining macros should have a special syntax with two lambda-lists when defining a setf function, or should use their normal syntax. The macros in question are defun, flet, labels, defgeneric, defmethod, and the :method option to defgeneric, generic-flet, generic-labels, and with-added-methods. In favor of two lambda-lists is that it's easier for the programmer to see which parameter is bound to the new value to be stored. In favor of one lambda-list is syntactic consistency between setf functions and regular functions. At the meeting two weeks ago, we favored two lambda-lists, but I now believe that that was a mistake. The rule that the new value is the last required argument should not be at all difficult for programmers to understand. Syntactic consistency is important. I believe making it be the first argument is better because the rule you propose loses in the following scenario. (defun foo (a b) ..) (defun (setf foo) (a b new-value) ..) (defun code-calling-setf-of-foo () (setf (foo a b) c)) Now at this point the programmer realizes that they would rather have the second argument to FOO be optional. But they are screwed because they have to go back and recompile all the code that uses setf of foo. The remaining issue is a scoping issue. We have introduced lexically local setf functions, where before Common Lisp only had lexically global setf macros. Thus the namespace of setf operators has been extended to have a lexical component, just like the namespace of regular operators. (Recall that "operator" means the union of functions, macros, and special forms). Regular functions and setf functions naturally come in pairs, but since they are defined separately we have to specify what happens in various cases where only one is defined at a given lexical contour. Scoping is not a problem in my proposal provided the programmer never uses defsetf. Because setf always expands the same way, all the programmer needs to do is provide lexical definitions for the actual setf function (SETF FOO). -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 17:31:40 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:17:34 PDT Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 14:15:01 PDT Date: Fri, 2 Oct 87 14:14 PDT From: Gregor.pa@Xerox.COM Subject: no-applicable-method To: David A. Moon cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871002140319.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Message-ID: <871002141420.0.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: Fri, 2 Oct 87 14:03 EDT From: David A. Moon Gregor, maybe you're still behind on your mail? right -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 17:18:29 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:04:31 PDT Received: from relay2.cs.net by RELAY.CS.NET id ah15107; 2 Oct 87 16:23 EDT Received: from csl.ti.com by RELAY.CS.NET id bn13177; 2 Oct 87 16:20 EDT Received: from Jenner by tilde id AA20526; Thu, 1 Oct 87 14:33:29 CDT Message-Id: <2769103900-16110287@Jenner> Date: Thu, 1 Oct 87 14:31:40 CDT From: Patrick H Dussud To: kempf%hplabsz@hplabs.hp.com Cc: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Exact type In-Reply-To: Msg of Wed, 30 Sep 87 14:16:36 MST from kempf%hplabsz@hplabs.hp.com > The user shouldn't expect > that an argument will be exactly of this built-in type. On some > machines, you cannot expect an cons cell argument to be always of the > exact type CONS. > Now I think I understand. We're coming from two different directions, as far as typing is concerned. Your direction seems to be the structural equivalence one, that is, two data items are of the same exact type if they have the same structure. My direction is operator equivalence, two items have the same exact type if you can apply the same set of operators to them. For me (this is, if I understand you proposal on optimization correctly) two types are the same if their applicable methods are the same for all of their operators. It is a necessary condition for method discrimination optimization. If you have a built-in type, say CONS and you write: (defun foo (x a) (declare (exact-type cons X)) (rplacd X a) a) The compiler would assume that it knows what methods are applicable to this call to REPLACD and will do some useful optimizations. However, it may happen that the system supplies foo with a CONS cell of type STACK-CONS, that you (portable user) didn't expect. The function foo would not work under this condition because RPLACD has a method defined on STACK-CONS, shadowing the one on CONS. I'll rewrite the Cleanup Committee submission to reflect the restriction you requested (unless I hear other objections), but I'd suggest we change the name back to EXACT-CLASS, since the built-in types are no longer covered. OK.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 17:17:03 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:04:11 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247684; Fri 2-Oct-87 17:05:10 EDT Date: Fri, 2 Oct 87 17:05 EDT From: David A. Moon Subject: Re: Can defgeneric provide defaults for &key args To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871002-134320-6130@Xerox> Message-ID: <871002170519.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 2 Oct 87 13:43 PDT From: Danny Bobrow There should be no distinction in defaulting rules between optional and keyword arguments. I like that way of putting it. A very succinct principle that is easy to state and easy to understand.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 17:13:55 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 14:00:26 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 13:50:07 PDT Date: 2 Oct 87 13:50 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: no-applicable-method In-reply-to: David A. Moon 's message of Fri, 2 Oct 87 14:03 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871002-135007-6157@Xerox> (no-applicable-method generic-function first-argument &rest all-arguments) This all looks fine except for what I think is a bug in the example. I thought we already changed the definition from (defgeneric no-applicable-method (generic-function first-argument &rest all-arguments)) to (defgeneric no-applicable-method (generic-function all-arguments)) I agree. One must redefine no-applicable-method to call another generic function that is specialized on the first argument. (defmethod no-applicable-method (generic-function all-arguments) (forward-message (car all-arguments) *elsewhere* (list generic-function all-arguments))) where the forwarder type understands the method forward-message, and no other. Alternatively, no-applicable-method could search the argument list for an element of the forwarder class to send the message to, else signal an error. This would not make it so dependent on the first argument.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 16:56:37 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 13:42:50 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 13:43:20 PDT Date: 2 Oct 87 13:43 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Can defgeneric provide defaults for &key args In-reply-to: David A. Moon 's message of Fri, 2 Oct 87 13:33 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871002-134320-6130@Xerox> We went through this issue at enormous length about a year ago, maybe a little less than a year. I expect you can find the rationale for the way generic function argument defaulting is now specified in the mail archives. If we had maintained a Design Rationale document as we said we would, it would be in there too. I, for one, don't feel eager to repeat that lengthy discussion again. I remember the reasons, but at that time did not have the same congruence rule for keyword arguments. However, I take it from your response that you feel the same arguments still apply. After some more thought, I agree with you. There should be no distinction in defaulting rules between optional and keyword arguments.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 16:11:14 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 12:55:46 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247593; Fri 2-Oct-87 15:56:41 EDT Date: Fri, 2 Oct 87 15:56 EDT From: David A. Moon Subject: Re: Constructors To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871002-113229-5844@Xerox> Message-ID: <871002155644.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Evidently my proposal for constructors wasn't very well written, since so far no one who has read it (and sent mail) has understood it. Date: 2 Oct 87 11:32 PDT From: Danny Bobrow (2) Coordination with class redefinition Moon argues that creating an option makes constructors lexically local. But the validity of the constructor is dependent on information that is inherited from many classes and methods. Hence being included in the class definition is not as useful as say the :initarg or :accessor slot-options, which are adjacent to all the information used in their construction. And :initarg or :accessor slot-options don't effect anything in subclasses (except for optimizations) I can't understand anything in the above paragraph. I never said anything about lexical locality, unless you mean "A much simpler way is to make the constructor syntactically part of the DEFCLASS, so it naturally gets updated at the same time as the rest of the DEFCLASS.", which refers to the linkage between the class and the constructor function necessary for the automatic updating discussed below. The :initarg and :accessor slot options certainly do affect subclasses. However, I don't see that's relevant, since the :constructor option does not affect subclasses. The effect of the :accessor slot option certainly does depend on sub and superclasses, in any system that optimizes compilation of SLOT-VALUE, because the position of a slot is not determined by the single DEFCLASS form. I'm obviously missing whatever point you were trying to make here. Making this updating automatic is a convenience for programmers, so they don't have to remember to do it by hand. I don't undertand which things can be done automagically. If I change the name of an initarg or method keyword argument, should the text in which constructors used the old name be changed? Clearly not. What other changes can be handled that are interesting? What Moon is suggesting is a general mechanism for notifying the user when the names of keyword arguments change in a method, so calls can be changed. That's certainly not what I'm proposing. I thought it was clear from the two sentences preceding the one you quoted what was being updated: "its initargs and their default values." I should have also mentioned compiler optimizations in this paragraph, rather than deferring them to later. Although :default-initargs is enough to make the point, compiler optimizations are in practice the major part of the updating burden. Look, it's very simple. If we're going to have a way to optimize out the interpretive processing that a naive implementation of MAKE-INSTANCE has to do, and generate specialized compiled code for making instances, then we have to have some way to redo this optimization when something changes. I claim it would be terrible for programmers to have to do that by hand. I claim that constructors are a better way to keep track of this automatically than any other way, because the special processing is confined to a system generated function, and kept away from user written functions. So what are the alternatives? We can decide that we don't care about speeding up object creation that much, or someone can propose a specific, coherent alternative. (3) More efficient than MAKE-INSTANCE ... Gregor has argued that calls to MAKE-INSTANCE with a constant first argument can be equally optimized ...In either case, if we are going to have this type of mechanism, I would much rather make it explicitly visible as a :CONSTRUCTOR option than have it operating behind the scenes in some vaguely defined way. But I thought the whole point of optimization mechanisms is that they would operate behind the scenes. I don't quite understand the phrase "the inherent complexity of making that mechanism generally available" in this context. I thought this was specific to make-instance, and that the only other mechanism was a hidden mechanism for generating functions from a particular type of call, rather than the optimization tricks. I guess neither of us can figure out what the other is talking about here. Maybe my previous paragraph makes this more clear: I hope so. If not, you should respond with something very specific, such as an example showing exactly what a programmer would write to get an efficient constructor. Perhaps it should be something that has the same semantics as (defclass class1 () ((a :initarg :a) (b :initarg :b))) (defclass class2 (class1) ((c :initarg :c) table) (:default-initargs :b 1) (:constructor make-2 (a &optional n b c))) (defmethod initialize-instance :after ((x class2) &key (n 10)) (setf (slot-value x 'table) (make-array n))) (make-2 "foo" 5) My high order conclusion is that - constructors are for writers of code, not readers, I agree or disagree depending on what you mean. The :constructor option is primarily an aid to writers of code, although of course it's somewhat easier to read than the equivalent written out as a defun. Calling a function to construct something, instead of calling MAKE-INSTANCE directly, is primarily an aid to readers of code, although it's also useful to writers, as any form of modularity is. - optimizations should be for system implementers, not something that we force the casual user to be aware of Precisely why I want to package the optimization into a :constructor option instead of making it visible to the writer of the function to construct something. - programming environments should support finding callers of methods whose arguments have changed. We might ask what hooks CLOS should provide for such an environmental feature. I assume when you say "methods" you mean "generic functions"; people don't call methods. I don't think CLOS has to provide any hooks for this, since I don't think the issue is significantly different for generic functions than for regular functions. I agree wholeheartedly that programming environments should provide support for this.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 15:08:04 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:53:56 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247454; Fri 2-Oct-87 14:53:25 EDT Date: Fri, 2 Oct 87 14:53 EDT From: David A. Moon Subject: Re: Constructors To: kempf%hplabsz@hplabs.HP.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <9321.560191280@hplabsz> Message-ID: <871002145323.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Fri, 02 Oct 87 10:41:20 MDT From: kempf%hplabsz@hplabs.HP.COM ....In the case of a class option, the association between a constructor name and a class name is made in the DEFCLASS form, but the constructor must actually be defined in a seperate form, as a method or function. From the point of view of someone reading the code (barring comments, of course) the fact that a particular method is a constructor is only apparent if they look back at the DEFCLASS form. Jim, I'm afraid you misunderstood what I was proposing, in an important way. The :constructor option to defclass completely takes care of defining the constructor; there is no separate form that "actually defines" it. Also, constructors are not methods. Thus in your example (defclass udc () (a b c) (:constructor udc-cons)) (defun udc-cons (a b c) (list a b c)) you are defining the function udc-cons twice. First you define it as a constructor, then you clobber that definition. Your example is semantically the same as (defclass udc () (a b c)) (defun udc-cons (&key) (make-instance 'udc)) (defun udc-cons (a b c) (list a b c)) As best I can tell, the rest of your comments aren't really applicable, once this misperception is realized. If after reading this you still think there are problems with constructors, could you send another message? I certainly want to be aware of any real semantic problems. At least one thing is clear from this, which is that if we put in constructors the explanation in the spec will have to be written more clearly than the explanation in the draft proposal I mailed out, so readers cannot misunderstand it in this way. I am not surprised by this.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 14:47:05 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:32:27 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 02 OCT 87 11:32:29 PDT Date: 2 Oct 87 11:32 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Constructors In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Fri, 02 Oct 87 10:41:20 MDT To: kempf%hplabsz@hplabs.HP.COM cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871002-113229-5844@Xerox> Moon argues that constructors are good because they provide: (1) A cleaner interface for the caller This is an argument for a functional interface that buries the name. A defun does that, as Moon points out. Some reasons to have a :CONSTRUCTOR option in DEFCLASS are - to make it easier and more convenient for users to create constructors - :CONSTRUCTOR is a convenient abbreviation for something you could do yourself in a more long-winded way, just like :ACCESSOR Isn't this another case of making something easier to type, and harder to read? We are talking about a few extra characters. Are the following really MUCH more long-winded than the constructor option? (defun make-foo (&rest initargs) (apply #' make-instance 'foo initargs)) (defun make-foo-2 (&key k1 k2) (make-instance 'foo :k1 k1 :k2 k2)) [Another] reason to have a :CONSTRUCTOR option in DEFCLASS [is] - to be culturally consistent with DEFSTRUCT We certainly have ignored the notion of being "culturally consistent with DEFSTRUCT" -- to quote Moon "that syntax was designed a long time ago". (2) Coordination with class redefinition Moon argues that creating an option makes constructors lexically local. But the validity of the constructor is dependent on information that is inherited from many classes and methods. Hence being included in the class definition is not as useful as say the :initarg or :accessor slot-options, which are adjacent to all the information used in their construction. And :initarg or :accessor slot-options don't effect anything in subclasses (except for optimizations) Making this updating automatic is a convenience for programmers, so they don't have to remember to do it by hand. I don't undertand which things can be done automagically. If I change the name of an initarg or method keyword argument, should the text in which constructors used the old name be changed? Clearly not. What other changes can be handled that are interesting? What Moon is suggesting is a general mechanism for notifying the user when the names of keyword arguments change in a method, so calls can be changed. (3) More efficient than MAKE-INSTANCE ... Gregor has argued that calls to MAKE-INSTANCE with a constant first argument can be equally optimized ...In either case, if we are going to have this type of mechanism, I would much rather make it explicitly visible as a :CONSTRUCTOR option than have it operating behind the scenes in some vaguely defined way. But I thought the whole point of optimization mechanisms is that they would operate behind the scenes. I don't quite understand the phrase "the inherent complexity of making that mechanism generally available" in this context. I thought this was specific to make-instance, and that the only other mechanism was a hidden mechanism for generating functions from a particular type of call, rather than the optimization tricks. My high order conclusion is that - constructors are for writers of code, not readers, - optimizations should be for system implementers, not something that we force the casual user to be aware of - programming environments should support finding callers of methods whose arguments have changed. We might ask what hooks CLOS should provide for such an environmental feature.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 14:16:34 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 11:02:25 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247364; Fri 2-Oct-87 14:03:15 EDT Date: Fri, 2 Oct 87 14:03 EDT From: David A. Moon Subject: no-applicable-method To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871002105236.9.GREGOR@SPIFF.isl.parc.xerox.com> Message-ID: <871002140319.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Fri, 2 Oct 87 10:52 PDT From: Gregor.pa@Xerox.COM Date: 24 Sep 87 08:55 PDT From: Bobrow.pa (no-applicable-method generic-function first-argument &rest all-arguments) This all looks fine except for what I think is a bug in the example. I thought we already changed the definition from (defgeneric no-applicable-method (generic-function first-argument &rest all-arguments)) to (defgeneric no-applicable-method (generic-function all-arguments)) Gregor, maybe you're still behind on your mail?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 14:08:04 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:54:05 PDT Received: from Semillon.ms by ArpaGateway.ms ; 02 OCT 87 10:53:18 PDT Date: Fri, 2 Oct 87 10:52 PDT From: Gregor.pa@Xerox.COM Subject: no-applicable-method To: Bobrow.pa@Xerox.COM cc: Common-Lisp-Object-System@Sail.stanford.edu In-Reply-To: <870924-085516-15017@Xerox> Message-ID: <871002105236.9.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: 24 Sep 87 08:55 PDT From: Bobrow.pa (no-applicable-method generic-function first-argument &rest all-arguments) This all looks fine except for what I think is a bug in the example. To use no-applicable-method to build forwarders, we need a class that is not a subclass of any class except T; hence no methods specialized on this argument will be applicable to instances of this class. Hence all calls using an instance of this class as first argument will cause a trap to no-applicable-method. We write: (defmethod no-applicable-method (g-f (first forwarder) &rest args) (send-elsewhere *place* gf first args))) Actually, I think the following is better: (defmethod no-applicable-method (g-f (first forwarder) &rest args) (send-elsewhere *place* gf args)) The point being that this makes it more clear that the &rest argument really contains all the arguments (the first arg appears in two places). -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 13:46:17 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:32:28 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 247304; Fri 2-Oct-87 13:33:29 EDT Date: Fri, 2 Oct 87 13:33 EDT From: David A. Moon Subject: Can defgeneric provide defaults for &key args To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871001-105240-3994@Xerox>, <9427.560191962@hplabsz> Message-ID: <871002133333.0.MOON@EUPHRATES.SCRC.Symbolics.COM> We went through this issue at enormous length about a year ago, maybe a little less than a year. I expect you can find the rationale for the way generic function argument defaulting is now specified in the mail archives. If we had maintained a Design Rationale document as we said we would, it would be in there too. I, for one, don't feel eager to repeat that lengthy discussion again.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 13:30:54 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 10:17:21 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Fri, 2 Oct 87 10:17:21 PDT Received: from hplabsz.hpl.hp.com by hplms2; Fri, 2 Oct 87 09:51:46 pdt Return-Path: Received: from hplabsz by hplabsz; Fri, 2 Oct 87 10:52:45 pdt To: Danny Bobrow Cc: Common-Lisp-Object-System@sail.stanford.edu Subject: Re: Can defgeneric provide defaults for &key args X-Mailer: mh6.5 In-Reply-To: Your message of 01 Oct 87 10:52:00 -0700. <871001-105240-3994@Xerox> Date: Fri, 02 Oct 87 10:52:42 MDT Message-Id: <9427.560191962@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > I don't think the rules allow a default value to be specified for a > keyword argument in defgeneric now, even though all methods must accept > such keys? Should it be allowed to support a uniform default? Was there some reason why defaults shouldn't be allowed, other than the case where two different methods would have two different defaults? Offhand, I can't think of any reason why a uniform default shouldn't be allowed.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 12:57:16 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Oct 87 09:41:53 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Fri, 2 Oct 87 09:41:13 PDT Received: from hplabsz.hpl.hp.com by hplms2; Fri, 2 Oct 87 09:40:28 pdt Return-Path: Received: from hplabsz by hplabsz; Fri, 2 Oct 87 10:41:23 pdt To: "David A. Moon" Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: Constructors X-Mailer: mh6.5 In-Reply-To: Your message of Wed, 30 Sep 87 12:37:00 -0400. <870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Fri, 02 Oct 87 10:41:20 MDT Message-Id: <9321.560191280@hplabsz> From: kempf%hplabsz@hplabs.HP.COM After reading through Moon's well thought out and well articulated proposal for constructors, I have two comments. The first is syntatic, the second semantic THE SYNTACTIC The syntax of the DEFCLASS form is already fairly complex, and adding an additional option will add yet another construct to this special sublanguage. If constructors are to be added at all (and see the next section for arguments why they shouldn't be), then I think a smoother integration would be to add them as a full fledged form, say DEFINE-CLASS-CONSTRUCTOR. The advantage of this over having a class option are that the implementation of the constructor (in the form of code) is locally close to the declaration of the association between the constructor name and the class name. In the case of a class option, the association between a constructor name and a class name is made in the DEFCLASS form, but the constructor must actually be defined in a seperate form, as a method or function. From the point of view of someone reading the code (barring comments, of course) the fact that a particular method is a constructor is only apparent if they look back at the DEFCLASS form. I think the advantages of grouping the definition of the constructor and the declaration of the association between the constructor name and the class name outweigh having the class definition and the constructor name locally close. THE SEMANTIC To motivate the following discussion, consider that constructors are added to the language, and the following code is written using them: (defclass udc () (a b c) (:constructor udc-cons)) (defun udc-cons (a b c) (list a b c)) (defmethod doit ((self udc)) (format T "In DOIT for UDC...~S~%" self)) (defmethod doit ((self list)) (format T "In DOIT for LIST...~S~%" self)) (setf obj (udc-cons 1 2 3)) (doit obj) What happens? Is OBJ a LIST or a UDC? Since it is not possible to subclass the built-in classes using the default, system supplied metaclasses, it cannot be both. Either the structure of a UDC instance is more than a list (meaning that the constructor code, as written, must be augmented to add some hidden state), or we have a semantic ambiguity which must be resolved arbitrarily. The philisophical side of this has to do with how I'd like to think we want to encourage people to think about the metaclass protocol. The way I see it (and I may be wrong), among other things, the metaclass controls the underlying representation of an instance. Users defining classes should be encouraged to think about their classes in a more abstract way, and not have to be concerned about the representation. If they are concerned about the representation, then an ALLOCATE-INSTANCE method can be written to control it. It's the job of the compiler writer to be sure that the default allocation is efficient enough so that people are encouraged to use it. Considering that the metaclass protocol is still in the draft stage, it's a bit difficult to argue cases, but I think the above example could be resolved by writing a new metaclass which does let you subclass one of the built-in classes. It may be a lot of work, involving defining new generic function and method classes as well. The optimization considerations outlined in the proposal are certainly of concern, especially for conventional hardware, but, as the example indicates, adding constructors could lead to having to add code to method dispatch to resolve ambiguities (or catch them as errors). Since method dispatch is THE critical item as far as optimization is concerned, it seems like adding constructors would be a case of robbing Peter to pay Paul. Of course, as was pointed out in the proposal, this makes the job of the compiler writer more difficult, if special cases for MAKE-INSTANCE are to be caught and optimized.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 2 Oct 87 00:13:54 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 21:00:24 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 21:00:43 PDT Date: 1 Oct 87 21:00 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Shared/class;instance/local In-reply-to: Dick Gabriel 's message of 01 Oct 87 16:21 PDT To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <871001-210043-4996@Xerox> I agree with Cointe about the intuitiveness of the name ``shared'' versus ``class.'' I agree with Danny about ``instance'' being better than ``local.'' Certainly a reasonable choice of vocabulary would be shared/instance. But then I would request that we use :shared, and :instance for the allocation options. I'm not sure we've come to grips with the real problem, though. The real problem is the distinction between the CLOS language constructs - in particular their syntax - and the English we use to describe them. There is no problem, aside from confusion, with having CLOS provide for slots with allocation type :class and calling such a slot a shared slot. Yes, it is confusion I would like to avoid, now and with at least some forseeable extensions. It is simpler to remember to use the descriptive term rather than a technofied synonym, or even to remember a technofied if it is used as the descriptive term. If I were to contemplate rewriting the CLOS specification to use the term ``class'' where ``shared'' was used before, I would opt for re-phrasing the noun phrase ``shared slot'' as ``a slot whose allocation type is :class'' in order to be precise. In this specification document, perhaps that is what we should do, whatever vocabulary we settle on. I thought precision was our principal criterion.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 1 Oct 87 22:27:05 EDT Received: from Salvador.ms by ArpaGateway.ms ; 01 OCT 87 17:35:40 PDT Return-Path: <@RELAY.CS.NET:sridhar@tajmahal.spt.tek.com> Redistributed: CommonLoops.PA Received: from RELAY.CS.NET by Xerox.COM ; 01 OCT 87 17:32:35 PDT Received: from relay2.cs.net by RELAY.CS.NET id ai06564; 1 Oct 87 15:56 EDT Received: from tektronix.tek.com by RELAY.CS.NET id aw05493; 1 Oct 87 15:49 EDT Received: by tektronix.TEK.COM (5.51/6.24) id AA14613; Thu, 1 Oct 87 09:18:23 PDT Received: from tajmahal.SPT (tajmahal.TEK) by tekcrl.TEK.COM (5.51/6.24) id AA22094; Thu, 1 Oct 87 09:20:08 PDT Received: by tajmahal.SPT (5.17/Tek) id AA00912; Thu, 1 Oct 87 09:19:05 PDT From: S Sridhar Message-Id: <8710011619.AA00912@tajmahal.SPT> Date: Thu, 1 Oct 87 09:19:00 PDT To: CommonLoops.PA@Xerox.COM Subject: Pl delete me. In-Reply-To: Your Message of Wed, 30 Sep 87 13:50:49 MST from the mailing list. My mailing addr in your list may appear as sridhar@tekchips.tek.com or some csnet variant. s. sridhar tektronix inc. email: sridhar@spt.tek.com  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 1 Oct 87 20:38:09 EDT Received: from Semillon.ms by ArpaGateway.ms ; 01 OCT 87 17:15:03 PDT Date: Thu, 1 Oct 87 17:12 PDT From: Gregor.pa@Xerox.COM Subject: Re: adding side effects to defmethod? To: Rick.Busdiecker@cs.cmu.edu cc: CommonLoops.PA@Xerox.COM In-Reply-To: <560104747/rfb@H.GP.CS.CMU.EDU> Message-ID: <871001171209.4.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: 1 Oct 87 12:39 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU BTW, If your compiler prints warnings for unused arguments then you'll notice that PCL/CLOS does some eval-time compilation! Is there any way to run interpreted? Will there be? At some point in the future PCL will no longer call the compiler at defmethod/defclass time. -------  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 1 Oct 87 20:37:59 EDT Received: from Semillon.ms by ArpaGateway.ms ; 01 OCT 87 17:13:22 PDT Date: Thu, 1 Oct 87 17:10 PDT From: Gregor.pa@Xerox.COM Subject: Re: adding side effects to defmethod? To: Rick.Busdiecker@cs.cmu.edu cc: CommonLoops.PA@Xerox.COM In-Reply-To: <560104747/rfb@H.GP.CS.CMU.EDU> Message-ID: <871001171028.1.GREGOR@SPIFF.isl.parc.xerox.com> Line-fold: no Date: 1 Oct 87 12:39 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU . . . and now I can. Below is some code which shows the general idea. If there's something grossly unreasonable about the way I've gone about this, please let me know. (defclass special-generic-function (clos::generic-function) () (:metaclass clos::funcallable-standard-class)) ;;; My, but this step simplified things! (setf (symbol-function 'do-something) (make-instance 'special-generic-function :name 'do-something)) In the next version of PCL, you will be able to do this by saying: (ensure-generic-function 'do-something :generic-function-class 'special-generic-function) (defmethod add-method ((generic-function special-generic-function) method) (format t "Some side-effect.~%") (call-next-method)) (defmethod do-something (some-argument some-other-argument) (format t "Something.~%")) Other than that this code is in fact exactly the right way to do this. All of these generic-functions and classes you are using are in the current *draft* of the meta object spec. -------  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 19:34:10 EDT Date: 01 Oct 87 1621 PDT From: Dick Gabriel Subject: Shared/class;instance/local To: common-lisp-object-system@SAIL.STANFORD.EDU I agree with Cointe about the intuitiveness of the name ``shared'' versus ``class.'' I agree with Danny about ``instance'' being better than ``local.'' I'm not sure we've come to grips with the real problem, though. The real problem is the distinction between the CLOS language constructs - in particular their syntax - and the English we use to describe them. There is no problem, aside from confusion, with having CLOS provide for slots with allocation type :class and calling such a slot a shared slot. For example, we can write a piece of code like this: (let ((n 0)) #'(lambda () (incf n))) and describe it as producing a closure, though the string ``closure'' appears nowhere in the piece of code. One rule of technical writing is to avoid creating names for objects that are compound nouns where some or all of the nouns are jargon words. The term ``shared slot'' is a normal English noun phrase because ``shared'' is a normal English adjective. The term ``class slot'' is a compound jargon term. To be blunter about it, if a naive weenie saw the term ``class slot,'' he might think, ``how nice, a class slot in a mediocre instance!'' The phrase ``:class slot'' is even worse, because ``:class'' is not a word (this is why you never see LGD and me write ``.... CLASS-CHANGED is a generic function that....'' but ``The generic function CLASS-CHANGED....'' because in the latter construction ``CLASS-CHANGED'' is used as a name referred to by the text rather than as a word in it.) If I were to contemplate rewriting the CLOS specification to use the term ``class'' where ``shared'' was used before, I would opt for re-phrasing the noun phrase ``shared slot'' as ``a slot whose allocation type is :class'' in order to be precise. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 15:58:38 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 12:44:44 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 12:44:18 PDT Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 12:43:38 pdt Return-Path: Received: from hplabsz by hplabsz; Thu, 1 Oct 87 13:44:34 pdt To: Danny Bobrow Cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@sail.stanford.edu Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE X-Mailer: mh6.5 In-Reply-To: Your message of 01 Oct 87 11:01:00 -0700. <871001-110144-4013@Xerox> Date: Thu, 01 Oct 87 13:44:31 MDT Message-Id: <27017.560115871@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > One could do the same thing as: > (defmethod change-class > ((p1 x-y-point) (class (eql (class-named 'rho-theta-point)))) > (let > ( (p2 (call-next-method)) ) > (with-slots (p2 rho theta) > (setf rho (rho p1)) > (setf theta (theta p1))))) > Two problems with what you say: > 1) After the call-next-method p1 is EQL to p2, and p1 is no longer an x y poi nt. > 2) Even if this worked, it wouldn't work for a subclass of rho-theta point. Right. It is pretty gross code anyway.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 14:32:12 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 11:17:38 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 11:01:44 PDT Date: 1 Oct 87 11:01 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 01 Oct 87 11:16:44 MDT To: kempf%hplabsz@hplabs.HP.COM cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu Message-ID: <871001-110144-4013@Xerox> > Yes. First, it is possible to specialize class-changed on the basis of > both classes, and secondly, one can use methods on the class of the > first (previous) object e.g. > (defmethod class-changed ((p1 x-y-point) (p2 rho-theta-point)) > (with-slots (p2 rho theta) > (setf rho (rho p1) > theta (theta p1)))) > > (defclass class-changed ((v1 directed-vector) (p rho-theta-point)) > ...) One could do the same thing as: (defmethod change-class ((p1 x-y-point) (class (eql (class-named 'rho-theta-point)))) (let ( (p2 (call-next-method)) ) (with-slots (p2 rho theta) (setf rho (rho p1)) (setf theta (theta p1))))) Two problems with what you say: 1) After the call-next-method p1 is EQL to p2, and p1 is no longer an x y point. 2) Even if this worked, it wouldn't work for a subclass of rho-theta point.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 14:31:59 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 11:17:23 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 10:52:40 PDT Date: 1 Oct 87 10:52 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Can defgeneric provide defaults for &key args To: Common-Lisp-Object-System@sail.stanford.edu cc: Bobrow.pa@Xerox.COM Message-ID: <871001-105240-3994@Xerox> Consider the following example of the new regime with lambda list congruence. I don't think the rules allow a default value to be specified for a keyword argument in defgeneric now, even though all methods must accept such keys? Should it be allowed to support a uniform default? Example: (defgeneric width &key (scale-factor 1)) (defmethod width ((s string) &key scale-factor (font *standard-font*)) ...) (defmethod width ((s bitmap) &key scale-factor paint-fn) ...) The alternative is: (defgeneric width &key scale-factor) (defmethod width ((s string) &key (scale-factor 1)(font *standard-font*)) ...) (defmethod width ((s bitmap) &key (scale-factor 1) paint-fn) ...)  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 1 Oct 87 13:43:42 EDT Received: from Catawba.ms by ArpaGateway.ms ; 01 OCT 87 10:19:07 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 01 OCT 87 10:16:52 PDT Date: 1 Oct 87 12:39 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: CommonLoops.PA@Xerox.COM Subject: Re: adding side effects to defmethod? Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <560104747/rfb@H.GP.CS.CMU.EDU> From: Rick.Busdiecker@H.GP.CS.CMU.EDU I want to be able to have a form like: (defmethod button-pressed ((window x-window) event) . . .) have some side-effects . . . . . . and now I can. Below is some code which shows the general idea. If there's something grossly unreasonable about the way I've gone about this, please let me know. BTW, If your compiler prints warnings for unused arguments then you'll notice that PCL/CLOS does some eval-time compilation! Is there any way to run interpreted? Will there be? Rick - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;;; -*- Mode: Lisp; Package: SGF -*- ;;; (in-package "SGF" :use '("LISP" "CLOS")) (defclass special-generic-function (clos::generic-function) () (:metaclass clos::funcallable-standard-class)) ;;; My, but this step simplified things! (setf (symbol-function 'do-something) (make-instance 'special-generic-function :name 'do-something)) (defmethod add-method ((generic-function special-generic-function) method) (format t "Some side-effect.~%") (call-next-method)) (defmethod do-something (some-argument some-other-argument) (format t "Something.~%"))  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 13:32:11 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 10:16:58 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 10:16:36 PDT Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 10:16:02 pdt Return-Path: Received: from hplabsz by hplabsz; Thu, 1 Oct 87 11:16:49 pdt To: Danny Bobrow Cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@sail.stanford.edu Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE X-Mailer: mh6.5 In-Reply-To: Your message of 01 Oct 87 09:48:00 -0700. <871001-094833-3815@Xerox> Date: Thu, 01 Oct 87 11:16:44 MDT Message-Id: <23927.560107004@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Yes. First, it is possible to specialize class-changed on the basis of > both classes, and secondly, one can use methods on the class of the > first (previous) object e.g. > (defmethod class-changed ((p1 x-y-point) (p2 rho-theta-point)) > (with-slots (p2 rho theta) > (setf rho (rho p1) > theta (theta p1)))) > > (defclass class-changed ((v1 directed-vector) (p rho-theta-point)) > ...) One could do the same thing as: (defmethod change-class ((p1 x-y-point) (class (eql (class-named 'rho-theta-point)))) (let ( (p2 (call-next-method)) ) (with-slots (p2 rho theta) (setf rho (rho p1)) (setf theta (theta p1))))) (defmethod class-changed ((v1 directed-vector) (class (eql (class-named 'rho-theta-point)))) ... )  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 13:12:27 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:57:44 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 09:53:12 PDT Date: 1 Oct 87 09:53 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Amendments requiring additional writing In-reply-to: David A. Moon 's message of Thu, 1 Oct 87 11:50 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871001-095312-3834@Xerox> DGB I would prefer to say: The \CLOS\ guarantees that the user can change the definition of an existing class that is a standard-class, and cause its instances to be updated. Whether redefining a class that is not a standard-class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this. Moon I can't see any difference between these two paragraphs, except that your suggested replacement is less direct, because the reader has to turn elsewhere to find out what a standard-class is. As far as I can tell there are no programs that would work under the first paragraph but not under the second. It is exactly this level of indirection I am encouraging because it will not eventually be misleading. Later caveats about when defclass doesn't produce standard-classes will not change the correctness of this paragraph.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 13:05:26 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:50:38 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 09:48:33 PDT Date: 1 Oct 87 09:48 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 01 Oct 87 10:02:35 MST To: kempf%hplabsz@hplabs.HP.COM cc: common-lisp-object-system@sail.stanford.edu Message-ID: <871001-094833-3815@Xerox> But the semantic delta here seems very minor, since, in both cases, by the time the respective generic function gets the instance, the structure has changed. The only difference is how the information on the old instance is transferred to the generic function. In the case of UPDATE-OBSOLETE-INSTANCE, it is through lists of slots and their values, while through CLASS-CHANGED, it seems to be through a copy of the old instance. Why not simply replace CLASS-CHANGED? Am I missing something? Yes. First, it is possible to specialize class-changed on the basis of both classes, and secondly, one can use methods on the class of the first (previous) object e.g. (defmethod class-changed ((p1 x-y-point) (p2 rho-theta-point)) (with-slots (p2 rho theta) (setf rho (rho p1) theta (theta p1)))) (defclass class-changed ((v1 directed-vector) (p rho-theta-point)) ...)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 12:38:05 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:25:00 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 09:25:23 PDT Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 09:24:46 pdt Return-Path: Received: from hplabsz by hplabsz; Thu, 1 Oct 87 10:25:42 pdt To: common-lisp-object-system@sail.stanford.edu Subject: COERCE (not urgent) X-Mailer: mh6.5 Date: Thu, 01 Oct 87 10:25:39 MST Message-Id: <22184.560103939@hplabsz> From: kempf%hplabsz@hplabs.HP.COM Since COERCE is a Cleanup Committee issue, there is no urgency to finish electronic mail discussion for Dick and Linda before next Fri., but I thought I would post it so that people can start thinking about it. I'll summarize discussion by Oct. 17. ISSUE: How should (or even should) COERCE be changed to accommodate CLOS? REMARK: CLOS already has two mechanisms of changing an object's class: 1) Class redefinition (largely hidden, automatic, with some user defined hooks, smashes the instance) 2) CHANGE-CLASS (smashes the instance) ALTERNATIVES: 1) Leave COERCE as it currently is. That is, make no CLOS specific changes. 2) Keep COERCE a function and have an internal generic function, COERCE-USING-CLASS handle coercion when the second argument is a class object, or the type specifier is for a CLOS class. 3) Make COERCE a generic function, with one method handling coercion when the second argument is a type specifier and one when it is a class object. Note that the type specifier method would need to handle the case of a type specifier for a CLOS class by using SYMBOL-CLASS to get the class, then reinvoking the generic function. SEMANTICS FOR CLOS OBJECTS: COERCE creates a new instance of the second argument, initializing according to the initialization protocol for the class, and then copies named slots common between the two instances, modulo type errors. If the first argument is already of the class indicated by the second argument, it is returned without copying. Note that this corresponds roughly with the current semantics when the first argument is a sequence and the second argument is a subtype of SEQUENCE. ALTERNATIVE ADVANTAGES AND DISADVANTAGES: The advantages of 1) are obvious: no changes needed in the base Common Lisp. The advantage of 2) is that the class and type specifier functionality are segregated under different names, since the new generic function takes care of coercion for CLOS. The advantage of 3) is that it reduces name proliferation, and integrates CLOS more tightly into the language. In addition, users can write new methods which discriminate on the first argument, and take a type specifier for the second. The disadvantages of 1) are that users must write their own methods for coercion. The disadvantage of 2) is that it introduces Yet Another metaclass function (COERCE-USING-CLASS). The disadvantages of 3) are that users might do something dangerous with existing type specifiers (like define a method that coerces an integer into a list).  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 12:24:45 EDT Received: from [128.81.41.45] by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:11:01 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by ALLEGHENY.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 65682; Thu 1-Oct-87 11:51:05 EDT Date: Thu, 1 Oct 87 11:50 EDT From: David A. Moon Subject: Re: Amendments requiring additional writing To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <871001-083508-3628@Xerox> Message-ID: <871001115040.4.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 1 Oct 87 08:35 PDT From: Danny Bobrow I mostly agree. I notice consturctors still in there, although that is not yet agreed to. But the oner serious remaining problem is in the wording of the last paragraph (not a new one): The \CLOS\ guarantees that {\bf defclass} can be used to change the definition of an existing class that was previously defined by {\bf defclass} as long as the {\bf :metaclass} option is not used in either the old or the new definition. Whether {\bf defclass} is allowed to change the metaclass and whether redefining a class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this. The problem is that defclass without a metaclass option can be used with class-for-redefinition to keep the class other than standard-class. I would prefer to say: The \CLOS\ guarantees that the user can change the definition of an existing class that is a standard-class, and cause its instances to be updated. Whether redefining a class that is not a standard-class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this. I can't see any difference between these two paragraphs, except that your suggested replacement is less direct, because the reader has to turn elsewhere to find out what a standard-class is. As far as I can tell there are no programs that would work under the first paragraph but not under the second. However, I continue to have almost no opinion on metaclass issues until I have seen a description of metaclasses that I can understand.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 12:15:24 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 09:01:40 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 09:02:06 PDT Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 09:01:42 pdt Return-Path: Received: from hplabsz by hplabsz; Thu, 1 Oct 87 10:02:39 pdt To: common-lisp-object-system@sail.stanford.edu Subject: CLASS-CHANGED and UPDATE-OBSOLETE-INSTANCE X-Mailer: mh6.5 Date: Thu, 01 Oct 87 10:02:35 MST Message-Id: <22064.560102555@hplabsz> From: kempf%hplabsz@hplabs.HP.COM Aren't these generic functions essentially doing the same thing? I understand that a user wanting to smash an instance needs a generic function (CHANGE-CLASS) which would change the structure of the instance to reflect the new class, and initialize, but why have two ways of updating the new instance? The point of UPDATE-OBSOLETE-INSTANCE is to give a user hook into transferring information from the old instance to the new, and that seems also to be the point of CLASS-CHANGED. I agree that, in the case of UPDATE-OBSOLETE-INSTANCE, the class object and name are the same for the old and new instance, while, in the case of CLASS-CHANGED, this is not the case. But the semantic delta here seems very minor, since, in both cases, by the time the respective generic function gets the instance, the structure has changed. The only difference is how the information on the old instance is transferred to the generic function. In the case of UPDATE-OBSOLETE-INSTANCE, it is through lists of slots and their values, while through CLASS-CHANGED, it seems to be through a copy of the old instance. Why not simply replace CLASS-CHANGED? Am I missing something? jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 11:53:32 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:38:43 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 246119; Thu 1-Oct-87 11:39:32 EDT Date: Thu, 1 Oct 87 11:39 EDT From: David A. Moon Subject: Re: Should redefining a class reinitialize shared slots? To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870930-173045-3035@Xerox> Message-ID: <871001113935.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 30 Sep 87 17:30 PDT From: Danny Bobrow It seems to me the only predictable rules are: (1) all class slots retain their values when the class is redefined. (2) all class slots are reinitialized when the class is redefined. I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. Despite the fact that I think I would usually want to retain current values of class slots, I worry about a confusion of models for the user. Rule 2 is a pure text based model; Rule 1 is a semi-structural model. This leads to questions about what changes in a class slot cause it to get reinitialized? If I change the :type If I change the :initform If I change its order in the list of slots If I add another class slot before it in the list If I change its name If one were doing structural editing, then none of these would cause reinitialization (even a name change). When dealing with the defclass form as text, the answer is less clear -- even with respect to the name change i.e. consider changing to "all-instances" from "all-my-instances" or from "allinstances". The rule that CLOS has been using all along is that slot identity is determined entirely by the slot's name. It seems to me that this is visible in many places throughout CLOS. This means that the only edit that causes a class slot to get reinitialized is changing its name (it's not really meaningful to say the slot gets reinitialized in this case; rather, one slot is deleted and a new one is created and initialized). Changing any other attribute of the slot does not affect the slot's identity (with the one unfortunate exception that changing the allocation from instance to class (a.k.a. from local to shared) destroys the slot and creates and initializes a new slot). I think bringing in notions of editors of various types may actually only confuse the issue. After all, the semantics of classes in CLOS are defined in terms of the behavior of certain objects under certain operations, and are not tied to the syntax of the DEFCLASS form, right? DEFCLASS is only the most convenient way to define a class, not the only way. I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. I find these arguments strong, but still find rule 2 is most consistent. Rule 1 probably is desirable in most cases, but I think will be confusing when we consider the above cases -- again, shades of DWIM. My intuition is not strong on this, so I would like to see opinions from Gregor and Patrick (others too, of course). I vehemently disagree with the notion that rule 2 is consistent with the rest of CLOS. I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. RPG writes: There is a third option, which would be to specify the redefinition initialization action in the DEFCLASS as a class slot option (:retain or :reinitialize, for example). I don't think additional language features are useful here; in particular, I would hate to see options specified that depended on the value(s) of other option(s). I think we must make up our mind what model to be supported. I agree with this. We should only adopt this third option if it becomes clear that it solves problems that we need to solve and that neither of the other two options can cope with.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 11:50:20 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:36:46 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Thu, 1 Oct 87 08:36:23 PDT Received: from hplabsz.hpl.hp.com by hplms2; Thu, 1 Oct 87 08:36:05 pdt Return-Path: Received: from hplabsz by hplabsz; Thu, 1 Oct 87 09:37:02 pdt To: "David A. Moon" Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: Amendments requiring additional writing X-Mailer: mh6.5 In-Reply-To: Your message of Wed, 30 Sep 87 23:45:00 -0400. <870930234533.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Thu, 01 Oct 87 09:36:59 MST Message-Id: <21559.560101019@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Here is a replacement for pages 1-11 and 1-12, based on the referenced > mail and the latest CONCEP.TEX on SAIL. I offered to write this because This looks OK to me. We'll need a specification for UPDATE-INSTANCE-STRUCTURE in addition, for Section 2. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 11:48:46 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:34:38 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 08:35:08 PDT Date: 1 Oct 87 08:35 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Amendments requiring additional writing In-reply-to: David A. Moon 's message of Wed, 30 Sep 87 23:45 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <871001-083508-3628@Xerox> I mostly agree. I notice consturctors still in there, although that is not yet agreed to. But the oner serious remaining problem is in the wording of the last paragraph (not a new one): The \CLOS\ guarantees that {\bf defclass} can be used to change the definition of an existing class that was previously defined by {\bf defclass} as long as the {\bf :metaclass} option is not used in either the old or the new definition. Whether {\bf defclass} is allowed to change the metaclass and whether redefining a class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this. The problem is that defclass without a metaclass option can be used with class-for-redefinition to keep the class other than standard-class. I would prefer to say: The \CLOS\ guarantees that the user can change the definition of an existing class that is a standard-class, and cause its instances to be updated. Whether redefining a class that is not a standard-class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 11:36:04 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Oct 87 08:21:56 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 01 OCT 87 08:22:24 PDT Date: 1 Oct 87 08:22 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Shared/local;class/instance In-reply-to: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe)'s message of Wed, 30 Sep 87 22:56:32 +0100 To: mcvax!inria.inria.fr!cointe@uunet.UU.NET cc: Bobrow.pa@Xerox.COM, RPG@sail.stanford.edu, common-lisp-object-system@sail.stanford.edu Message-ID: <871001-082224-3610@Xerox> I strongly believe that :shared is a better name than :class. As a Smalltalk teacher i have big troubles with the Smalltalk non-symmetry between class/instance methods and class/instance variables. My (Smalltalk) point of view is that class variables should refer the instance variables of a class treated as an object. What should the other one be called. Would you prefer shared/instance? danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 1 Oct 87 03:05:12 EDT Received: from UUNET.UU.NET by SAIL.STANFORD.EDU with TCP; 30 Sep 87 23:52:50 PDT Received: from mcvax.UUCP by uunet.UU.NET (5.54/1.14) with UUCP id AA29175; Thu, 1 Oct 87 02:53:17 EDT Received: by mcvax.cwi.nl; Thu, 1 Oct 87 06:31:49 +0100 (MET) Received: by inria.inria.fr; Wed, 30 Sep 87 22:56:32 +0100 (MET) Date: Wed, 30 Sep 87 22:56:32 +0100 From: mcvax!inria.inria.fr!cointe@uunet.UU.NET (Pierre Cointe) Message-Id: <8709302156.AA16490@inria.inria.fr> To: Bobrow.pa@xerox.com, RPG@sail.stanford.edu Subject: Re: Shared/local;class/instance Cc: common-lisp-object-system@sail.stanford.edu I strongly believe that :shared is a better name than :class. As a Smalltalk teacher i have big troubles with the Smalltalk non-symmetry between class/instance methods and class/instance variables. My (Smalltalk) point of view is that class variables should refer the instance variables of a class treated as an object.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 23:58:19 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 20:44:43 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245796; Wed 30-Sep-87 23:45:30 EDT Date: Wed, 30 Sep 87 23:45 EDT From: David A. Moon Subject: Amendments requiring additional writing To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870925214129.4.MOON@EUPHRATES.SCRC.Symbolics.COM>, <870928-133654-19356@Xerox>, <870928184306.6.MOON@EUPHRATES.SCRC.Symbolics.COM>, <870929-085934-1876@Xerox>, <870929-180832-1165@Xerox>, <870930171107.8.MOON@EUPHRATES.SCRC.Symbolics.COM>, <870930171528.9.MOON@EUPHRATES.SCRC.Symbolics.COM>, The message of 30 Sep 87 18:21 EDT from Dick Gabriel , <870930-152906-2790@Xerox>, <870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM>, <870930-173045-3035@Xerox>, <13275.560047705@hplabsz> Message-ID: <870930234533.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Here is a replacement for pages 1-11 and 1-12, based on the referenced mail and the latest CONCEP.TEX on SAIL. I offered to write this because it incorporates an amended paragraph I sent out on 25 Sep, and because Danny asked me to write it because he said he was too busy to do any writing. Note that we will probably want a separate section explaining how to change the class of an object, using change-class. Note that class-changed and update-instance-structure are currently incompatible with respect to who evaluates the initforms; one of them has to be changed. I didn't attempt to write anything for change-class. We could always describe change-class only in the Function chapter, and not have a Concept section for it. I have not changed any local/shared/instance/class slot terminology. We can change that later if we agree on the new terminology. \beginSection{Redefining Classes} When a {\bf defclass} form is evaluated and a class with the given name already exists, the existing class is redefined. Redefining a class modifies the existing class object to reflect the new class definition; it does not create a new class object for the class. Any method created by an {\bf :accessor} or {\bf :reader} option specified by the old {\bf defclass} form is removed from the corresponding generic function unless that same method is specified by the new {\bf defclass} form; any function specified by the {\bf :constructor} option of the old {\bf defclass} form is removed from the corresponding symbol function cell. When the class $C$ is redefined, changes are propagated to instances of it and to instances of any of its subclasses. The updating of an instance whose class has been redefined (or any of whose superclasses have been redefined) occurs at an implementation-dependent time, but no later than the next time a slot of that instance is read or written. Updating an instance does not change its identity as defined by the {\bf eq} function. The updating process may change the slots of that particular instance, but it does not create a new instance. Whether updating an instance consumes storage is implementation dependent. If a class is redefined in such a way that the set of local slots accessible in an instance of the class is changed or the order of slots in storage is changed, the function {\bf update-instance-structure} is called whenever an instance of the class is updated, to complete the transformation from the old representation of the instance to the new representation. Implementations may choose to invoke {\bf update-instance-structure} under other circumstances as well. Programmers can define methods for {\bf update-instance-structure} to specify actions to be taken when an instance is updated. When {\bf update-instance-structure} is called, the structure of the instance has already been converted to conform to the new class definition, and newly added slots are uninitialized. Note that redefining a class may cause slots to be added or deleted. When an instance is updated, new slots are initialized and the values of deleted slots are discarded. Each local slot of the new version of the class with no slot by the same name in the old version of the class is initialized to the value of the corresponding {\bf :initform} option of the new class or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. This is the same as the initialization done by {\bf make-instance} except that no initialization methods are invoked and no {\bf make-instance} initialization arguments are present. This initialization is performed by the default primary method for {\bf update-instance-structure}. \eject If in the new version of the class there is a local slot of the same name as any slot in the old version of the class, the value of that slot is unchanged. This is true regardless of whether the old slot was a local slot or a shared slot. This means that if the slot has a value, the value returned by {\bf slot-value} after class redefinition is {\bf eql} to the value returned by {\bf slot-value} before class redefinition. Similarly, if the slot was uninitialized, it remains uninitialized. If in the new version of the class there is a shared slot of the same name as any shared slot in the old version of the class, the value of that slot is unchanged. If in the new version of the class there is a shared slot of the same name as any local slot in the old version of the class, that shared slot is initialized to the value of the corresponding {\bf :initform} option of the new class or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. Shared slots are updated at the moment of class redefinition and are not affected by the updating of an instance nor by the values of any local slots. The \CLOS\ guarantees that {\bf defclass} can be used to change the definition of an existing class that was previously defined by {\bf defclass} as long as the {\bf :metaclass} option is not used in either the old or the new definition. Whether {\bf defclass} is allowed to change the metaclass and whether redefining a class causes existing instances to be updated is up to the implementor of the particular metaclass. ``The \CLOS\ Meta-Object Protocol'' will describe how to control this. \endSection%{Redefining Classes}  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 21:10:59 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:56:36 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 17:30:45 PDT Date: 30 Sep 87 17:30 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Should redefining a class reinitialize shared slots? In-reply-to: David A. Moon 's message of Wed, 30 Sep 87 17:11 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870930-173045-3035@Xerox> It seems to me the only predictable rules are: (1) all class slots retain their values when the class is redefined. (2) all class slots are reinitialized when the class is redefined. I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. Despite the fact that I think I would usually want to retain current values of class slots, I worry about a confusion of models for the user. Rule 2 is a pure text based model; Rule 1 is a semi-structural model. This leads to questions about what changes in a class slot cause it to get reinitialized? If I change the :type If I change the :initform If I change its order in the list of slots If I add another class slot before it in the list If I change its name If one were doing structural editing, then none of these would cause reinitialization (even a name change). When dealing with the defclass form as text, the answer is less clear -- even with respect to the name change i.e. consider changing to "all-instances" from "all-my-instances" or from "allinstances". I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. I find these arguments strong, but still find rule 2 is most consistent. Rule 1 probably is desirable in most cases, but I think will be confusing when we consider the above cases -- again, shades of DWIM. My intuition is not strong on this, so I would like to see opinions from Gregor and Patrick (others too, of course). I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. RPG writes: There is a third option, which would be to specify the redefinition initialization action in the DEFCLASS as a class slot option (:retain or :reinitialize, for example). I don't think additional language features are useful here; in particular, I would hate to see options specified that depended on the value(s) of other option(s). I think we must make up our mind what model to be supported.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 21:01:13 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:47:52 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 17:47:50 PDT Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 17:47:30 pdt Return-Path: Received: from hplabsz by hplabsz; Wed, 30 Sep 87 18:48:27 pdt To: "David A. Moon" Cc: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Should redefining a class reinitialize shared slots? X-Mailer: mh6.5 In-Reply-To: Your message of Wed, 30 Sep 87 20:19:00 -0400. <870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Wed, 30 Sep 87 18:48:25 MST Message-Id: <13275.560047705@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Date: 30 Sep 87 1521 PDT > From: Dick Gabriel > ``It seems to me the only predictable rules are: > (1> ) all class slots retain their values when the class is redefined. > (2) all class slots are reinitialized when the class is redefined.'' > There is a third option, which would be to specify the redefinition > initialization action in the DEFCLASS as a class slot option (:retain or > :reinitialize, for example). > That's a good point. I could go along with that if we think the extra > complexity is justified. No. I think 2) is sufficient. jak  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 20:43:05 EDT Received: from Concord.ms by ArpaGateway.ms ; 30 SEP 87 17:15:39 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 30 SEP 87 17:14:14 PDT Date: 30 Sep 87 20:10 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: Danny Bobrow Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <560045443/rfb@H.GP.CS.CMU.EDU> From: Danny Bobrow No it doesn't because in the new definition of with-slots, you must specify which slots are being referred to by symbols, and this is independent of the class definition. Sounds good to me. Rick  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 20:32:47 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 17:19:18 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245685; Wed 30-Sep-87 20:19:43 EDT Date: Wed, 30 Sep 87 20:19 EDT From: David A. Moon Subject: Should redefining a class reinitialize shared slots? To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 30 Sep 87 18:21 EDT from Dick Gabriel Message-ID: <870930201953.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 30 Sep 87 1521 PDT From: Dick Gabriel ``It seems to me the only predictable rules are: (1) all class slots retain their values when the class is redefined. (2) all class slots are reinitialized when the class is redefined.'' There is a third option, which would be to specify the redefinition initialization action in the DEFCLASS as a class slot option (:retain or :reinitialize, for example). That's a good point. I could go along with that if we think the extra complexity is justified.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 19:33:32 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 16:19:11 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 15:30:51 PDT Date: 30 Sep 87 15:29 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: class/instance vs shared/local To: common-lisp-object-system@SAIL.STANFORD.EDU cc: Bobrow.pa@Xerox.COM Message-ID: <870930-153051-2792@Xerox> I feel strongly about using class and instance rather than shared and local. If no one else feels strongly, can we agree to go with these so we can get on with the documentation. (Dick -- you are the only one to argue against this. Is this OK with you?). danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 19:33:21 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 16:18:56 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 30 SEP 87 15:11:31 PDT Date: 30 Sep 87 15:11 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: next-method-p To:Common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870930-151131-2747@Xerox> I detect a consensus for next-method-p. If I hear no objections, I will send out a writeup in the next day (and/or Moon can put it in his file of decisions). danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 18:34:29 EDT Date: 30 Sep 87 1521 PDT From: Dick Gabriel Subject: Should redefining a class reinitialize shared slots? To: common-lisp-object-system@SAIL.STANFORD.EDU Moon writes: ``It seems to me the only predictable rules are: (1) all class slots retain their values when the class is redefined. (2) all class slots are reinitialized when the class is redefined.'' There is a third option, which would be to specify the redefinition initialization action in the DEFCLASS as a class slot option (:retain or :reinitialize, for example). Moon writes: ``instance -> class reinitializes the slot, because there is no distinguished instance from which to get the value.'' Well, we could have declarative slot combination, in which these values could be combined.... (hee, hee). -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 17:34:34 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 14:19:31 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245381; Wed 30-Sep-87 17:20:30 EDT Date: Wed, 30 Sep 87 17:20 EDT From: David A. Moon Subject: NEXT METHOD To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 30 Sep 87 17:03 EDT from Dick Gabriel Message-ID: <870930172036.0.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 30 Sep 87 1403 PDT From: Dick Gabriel I can support NEXT-METHOD-P, because I doubt there is much constructive use to which the next method could be put - funcall its method-function (?). Let's go with NEXT-METHOD-P. It sure seems to duck a lot of problems.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 17:27:03 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 14:10:06 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245367; Wed 30-Sep-87 17:10:57 EDT Date: Wed, 30 Sep 87 17:11 EDT From: David A. Moon Subject: Should redefining a class reinitialize shared slots? To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870929-085934-1876@Xerox> Message-ID: <870930171107.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 29 Sep 87 08:59 PDT From: Danny Bobrow I haven't been able to figure out what you mean here. Editing out the parts of your comment I don't understand leaves "Redefining the class should set the value of the class slots", which we've never said before and I don't think I agree with. Here are two cases to think about: (1) A class slot whose value is a list of all the instances, initialized to nil when the class is first defined and updated by an initialize-instance method. (2) A class slot whose value is the price of an instance, initialized by :initform in the defclass. In case 1, you surely don't want the slot value reset to nil when you redefine the class. In case 2, you might want to set the price to the new value of the :initform. If redefining a class always reinitializes class slots, you can't do case 1. If it never reinitializes class slots, you can work around case 2 by doing setf of slot-value at the same time as you redefine the class. These are interesting examples, and cause one to ponder. I think the difference here is like the difference between editing a function definition on a file and editing the actual function list structure with a structure editor. Changing a function using a structure editor affects existing calls, and editing the file cannot. I think that's a good analogy. Although, which existing calls are actually affected by changing a function with a structure editor probably depends a lot on what in the function you change, versus where in the function control is suspended, and also on implementation-dependent details such as whether you compile or not. Maybe that's part of the applicability of the analogy, though, in the sense that the issue never seems to be simple. Bring back APL\360, where editing a function automatically invalidated any activation records for that function, and announced "SI DAMAGE". I think the corresponding cases for classes are: use the metaobject protocol to update an existing class using the slot objects that currently exist, and reevaluating the defclass form. In the latter case, the specification only guarantees that class objectsame object identity is preserved, Well, what the specification actually says (87-002 page 1-12, very top of the page, sentence actually starts on the preceding page) is that values of class slots are preserved. So the issue is whether we want to change the specification. I think the specification now says that re-evaluating a defclass form is not like re-evaluating a defun form, but is more like structure editing: it patches an existing object rather than creating a new object. unless we want to go more into a DWIM mode, that is guess which items in the new definition are meant to yield the same result as the old case. The DWIM idea doesn't appeal to me since I can't figure out how to make it predictable. It seems to me the only predictable rules are: (1) all class slots retain their values when the class is redefined. (2) all class slots are reinitialized when the class is redefined. I prefer rule 1 because it is analogous to the rule for instance slots. Also, it's easier to reinitialize a slot that was retained than to retain a slot that was reinitialized, if a user wants to implement behavior different from the default. Revisiting in this light the rules for slots whose allocation is changed: class -> instance copies the slot value into each instance, again by analogy with the rule for instance slots (the value returned by SLOT-VALUE remains the same). instance -> class reinitializes the slot, because there is no distinguished instance from which to get the value.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 17:15:29 EDT Date: 30 Sep 87 1403 PDT From: Dick Gabriel Subject: NEXT METHOD To: common-lisp-object-system@SAIL.STANFORD.EDU JAK writes: ``I guess one could make an analogy with function calling. The programmer can either test if the function is bound before calling: (if (fboundp 'foo) (apply foo arglist))'' One could, but I think it's a bad analogy. Many methods can be written on a generic function, and it is sensible to suppose that the authors of the methods on that generic function might desire that his methods each call the next most specific one - method combination could be used, but assume not. In this case, the writer of each method will not know, a priori, whether there will be any other such methods. Therefore, the author of such a method will be thinking that his method will call the next most specific one, if it exists. In short, the test of whether there is such a further method is like the termination test in a control structure. Hence it is not like an exception. The author of the code JAK mentions is calling a specific function by name, and not be relative ``position'' from the current one. Thus, I regard his analogy as not convincing. I can support NEXT-METHOD-P, because I doubt there is much constructive use to which the next method could be put - funcall its method-function (?). -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 17:06:23 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:53:32 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 245353; Wed 30-Sep-87 16:54:29 EDT Date: Wed, 30 Sep 87 16:54 EDT From: David A. Moon Subject: Slot Inheritance To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <3388.559949911@hplabsz> Message-ID: <870930165439.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Tue, 29 Sep 87 15:38:31 MST From: kempf%hplabsz@hplabs.HP.COM > REVISED ``INHERITANCE OF SLOTS AND SLOT OPTIONS'' SECTION: This looks good to me, with the proviso that "shared slot" be replaced by whatever terminology we decide on. After reading through it, I can't find any ambiguity in the wording. The reference to :DYNAMIC slots needs to be removed, however. Right. The one I mailed out is identical, except for TEX commands, to what was handed out at the March X3J13 meeting, I believe. When put into the document it should need some minor editing to match the current state of the spec. I checked it again and found only the removal of :DYNAMIC and the addition of :INITARG. It seems to be more concise than the current description. Thanks.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 16:39:13 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:26:01 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 13:26:22 PDT Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 13:26:05 pdt Return-Path: Received: from hplabsz by hplabsz; Wed, 30 Sep 87 14:27:02 pdt To: Dick Gabriel Cc: Common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Various Decisions X-Mailer: mh6.5 In-Reply-To: Your message of 29 Sep 87 15:29:00 -0700. Date: Wed, 30 Sep 87 14:26:58 MST Message-Id: <9637.560032018@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > > On condition handlers instead of NEXT-METHOD: > Similarly, if it is the case (and I think it likely) that a programmer > frequently wants to CALL-NEXT-METHOD when there might not be one, then he > will likely want to write: > (when (next-method) (call-next-method)) > or use a non-error-signaling version of CALL-NEXT-METHOD rather than > program a condition handler. I guess one could make an analogy with function calling. The programmer can either test if the function is bound before calling: (if (fboundp 'foo) (apply foo arglist)) or go ahead and call it and take the exception if it's not: (catch-condition unbound-function &body (apply foo arglist)) So I guess it makes sense to have a way of checking if CALL-NEXT-METHOD is "bound" within the method, in addition. NEXT-METHOD-P, returning T or NIL, is fine with me. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 16:29:45 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Sep 87 13:15:51 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 13:16:01 PDT Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 13:15:42 pdt Return-Path: Received: from hplabsz by hplabsz; Wed, 30 Sep 87 14:16:39 pdt To: Patrick H Dussud Cc: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Exact type X-Mailer: mh6.5 In-Reply-To: Your message of Tue, 29 Sep 87 16:12:46 -0500. <2768937166-6092662@Jenner> Date: Wed, 30 Sep 87 14:16:36 MST Message-Id: <9580.560031396@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > The user shouldn't expect > that an argument will be exactly of this built-in type. On some > machines, you cannot expect an cons cell argument to be always of the > exact type CONS. > Now I think I understand. We're coming from two different directions, as far as typing is concerned. Your direction seems to be the structural equivalence one, that is, two data items are of the same exact type if they have the same structure. My direction is operator equivalence, two items have the same exact type if you can apply the same set of operators to them. As to which is better, I think this may be a religious issue, so I won't push on it. Both approaches have advantages and disadvantages, but the advantages of the operator equivalence approach are mostly in the ability to do compile time optimizations (which is what I had in mind as a use for EXACT-TYPE) that are particularly important on conventional machines. Since Common Lisp takes no stand on this issue, it's open for implementors to do as they feel is best (hiding the details under TYPEP and SUBTYPEP). I'll rewrite the Cleanup Committee submission to reflect the restriction you requested (unless I hear other objections), but I'd suggest we change the name back to EXACT-CLASS, since the built-in types are no longer covered. jak  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 16:13:39 EDT Received: from Salvador.ms by ArpaGateway.ms ; 30 SEP 87 12:53:28 PDT Return-Path: Redistributed: CommonLoops.PA Received: from hplabs.HP.COM (hplabs.hpl.hp.com) by Xerox.COM ; 30 SEP 87 12:51:17 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 12:50:17 PDT Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 12:49:55 pdt Return-Path: Received: from hplabsz by hplabsz; Wed, 30 Sep 87 13:50:52 pdt To: Rick.Busdiecker@cs.cmu.edu Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug X-Mailer: mh6.5 In-Reply-To: Your message of 30 Sep 87 13:07:00 -0400. <560020034/rfb@H.GP.CS.CMU.EDU> Date: Wed, 30 Sep 87 13:50:49 MST Message-Id: <9152.560029849@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > reasons. In the case of adding slot, with slots causes a new binding > for some symbol. Something like: > (defclass foo () (a)) > (defmethod bar ((foo foo)) > (let ((b :value-i-expect)) > (with-slots (foo) > . . .))) Within the WITH-SLOTS form, B is a lexical variable > (defclass foo () (a (b :value-that-breaks-my-code))) Now FOO has a slot named B. > (defmethod bar ((foo foo)) > (let ((b :value-i-expect)) > (with-slots ((foo :prefix foo-)) > ...))) Yes, this would prevent it. But your argument implies that one should *always* use the :PREFIX option, otherwise, this could happen in any case where a lexically scoped slot name could shadow an outer lexical variable. The same thing happens with lexically nested LETs, but because the cause of the change is usually local (unless the outer LET block is large) there is less of a problem. I don't think the problem here is so much with whether or not to use the :PREFIX option as with the semantics of WITH-SLOTS. In Smalltalk, CommonObjects, and other languages with "instance variable" like slot access, the slot name variable is privilidged within the scope of the method, and trying to rebind it results in an error. But this doesn't fit very well with Common Lisp's lexical scoping rules, and not at all with multimethods. So perhaps the solution is to provide a warning message at compile time if WITH-SLOTS tries to shadow an outer lexical variable. Our compiler does something similar with identifiers which are not declared SPECIAL and not lexical variables, and we have had a request from some of our developers to do the same with WITH-SLOTS. Jim Kempf kempf@hplabs.hp.com  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 16:13:26 EDT Received: from Catawba.ms by ArpaGateway.ms ; 30 SEP 87 11:09:19 PDT Return-Path: Redistributed: CommonLoops.PA Received: from hplabs.HP.COM (hplabs.hpl.hp.com) by Xerox.COM ; 30 SEP 87 11:06:21 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 11:05:29 PDT Received: from hplwhh (hplwhh) by hplms2; Wed, 30 Sep 87 11:05:05 pdt Return-Path: Received: from hplwhh.hpl.hp.com by hplwhh ; Wed, 30 Sep 87 11:00:15 pdt To: Gregor.pa@Xerox.COM Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug X-Mailer: mh6.5 In-Reply-To: Your message of 29 Sep 87 22:00:00 -0700. <870929-220237-1512@Xerox> Date: Wed, 30 Sep 87 11:00:12 PDT Message-Id: <27732.560023212@hplwhh> From: Warren Harris > * intern the symbols in the package of the prefix symbol > - often, this is likely to solve the problem presented in the second > bullet, but it won't work in general and is kind of a crock. Is there any logical justification for why this solution won't work? :Accessor-prefix could be considered to be supplying not only part of the name, but also the default package. I certainly find this: (defclass my::foo () ((lisp::list) (my::element) ...) (:accessor-prefix my::foo-)) preferable to: (defclass my::foo () ((lisp::list :accessor my::foo-list) (my::element :accessor my::foo-element) ...)) There are also some of us who still refuse to use prefixes on slot accessors because they obscure the genericness we are trying to achieve through subclassing. I don't want to have to remember that certain slots of a class are accessed with that class name as a prefix, and other slots are accessed with some parent classes name for a prefix. In this case I find :accessor-prefix NIL to be an invaluable shorthand to enumerating every slot name twice, once for the slot itself and once for the accessor function. If by taking away :accessor-prefix you're trying to keep us from being lazy (and inadvertantly defining accessors for slots that shouldn't have them by indiscriminant use of :accessor-prefix) perhaps this reason should be officially stated. Regarding with-slots: I've recently heard that in the future you're going to have to enumerate the slots you want to use in a with-slots form. I find the thought of doing this repulsive. Most of my methods tend to take the form: (defmethod m ((f foo) ...) (with-slots ((f :use-accessors nil)) ...)) and thus behave like classical methods anyway. This isn't because I don't know how to use multimethods (I use them when appropriate), but because classical methods in general are what you want 80% of the time. The use of "with-slots ... :use-accessors nil" (or slot-value for that matter) in CLOS is not just an ugly "back door" that violates encapsulation or is used for optimization, but is a necessity when specializing slot accessor methods. I haven't heard a good argument for denying methods on a class privileged access to that class's slots (of course multimethods complicates this, but that what :prefix is for), so I don't think taking away with-slots (by making it so painful to use) is the thing to do. Perhaps examples of problematic usage of with-slots and its :prefix option could shed some light.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 14:10:42 EDT Received: from Concord.ms by ArpaGateway.ms ; 30 SEP 87 10:46:05 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 30 SEP 87 10:44:31 PDT Date: 30 Sep 87 13:29 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: CommonLoops.PA@Xerox.COM Subject: adding side effects to defmethod? Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <560021353/rfb@H.GP.CS.CMU.EDU> I want to be able to have a form like: (defmethod button-pressed ((window x-window) event) . . .) have some side-effects, like calling XSelectInput in appropriate places. From reading the CLOS document (87-002) and poking around in the pcl sources, I decided to try the following: - Make a subclass of the clos::standard-generic-function class. - Specialize the clos:add-method method for that subclass. - Change the class of the clos::method-generic-function of the method returned by defmethod to be the subclass that I defined. Unfortunately, the change-class failed: Error in function CHANGE-CLASS. Wrong type argument, #, should have been of type SIMPLE-VECTOR. Is there a better approach to this sort of thing? Rick  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 14:10:31 EDT Received: from Chardonnay.ms by ArpaGateway.ms ; 30 SEP 87 10:32:38 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 30 SEP 87 10:29:28 PDT Date: 30 Sep 87 13:07 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: kempf%hplabsz@hplabs.HP.COM Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <560020034/rfb@H.GP.CS.CMU.EDU> From: kempf%hplabsz@hplabs.HP.COM > I think that that makes with-slots into a truly dangerous form. > Code that uses with-slots without the :prefix can be broken by adding a > slot to the class definition. That's true whether or not the :prefix option is there, and whether or not you use WITH-SLOTS or the accessor function directly. If you delete a slot (for example) the accessor function is undefined, so any method using the accessor function will break. Similarly, if you delete a slot even using the :PREFIX option, the code within the WITH-SLOTS would need to be changed, otherwise it will break when you try to reference the slot next time (precisely, a call to SLOT-MISSING will occur). The case of deleting a slot doesn't worry me as much since code that referenced a slot which no longer exists must be fixed for semantic reasons. In the case of adding slot, with slots causes a new binding for some symbol. Something like: (defclass foo () (a)) (defmethod bar ((foo foo)) (let ((b :value-i-expect)) (with-slots (foo) . . .))) . . . (defclass foo () (a (b :value-that-breaks-my-code))) shows how code might be broken in a way that (a) might not be related to the new semantics related to the slot addition and (b) could easily have been prevented locally in the bar method with: (defmethod bar ((foo foo)) (let ((b :value-i-expect)) (with-slots ((foo :prefix foo-)) ...))) Is there another mailing list where changes to the specification are being discussed before the decisions are made? Would someone please add me? Rick  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 30 Sep 87 12:55:15 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Sep 87 09:36:17 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244977; Wed 30-Sep-87 12:37:07 EDT Date: Wed, 30 Sep 87 12:37 EDT From: David A. Moon Subject: Constructors To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870930123711.3.MOON@EUPHRATES.SCRC.Symbolics.COM> This is a proposal to add constructors back into CLOS, now that the basic object creation protocol has been agreed upon. Note that this proposal has been greatly simplified compared to what was being discussed last spring. In response to several cogent objections that were raised, a number of problematic features have been removed and constructors have been made easier to understand and to use. While these proposed constructors are somewhat different from the constructors whose usefulness has been verified by their use in New Flavors, a survey of 242 constructors used in a variety of Flavors-based programs showed that these CLOS constructors should meet the needs of those programs, which I am assuming to be in some sense typical. The only real change to those programs would be the requirement that any slot to be filled by a constructor must have an initarg, and I don't think that presents any difficulty. Survey of 242 constructors for 237 different flavors: 83 with MAKE-INSTANCE-style arguments. Of the remaining 159 constructors: 140 with required arguments only, 8 also with optional or rest, 11 with keyword arguments. 0 with &aux parameters. 15 take no arguments, 102 only fill slots, 3 also specify area, 39 take initargs. 142 fill slots, of which 0 use the initarg rather than the slot name, and 85 fill slots that don't have initargs. 103 fill inherited slots. WHY HAVE CONSTRUCTORS? (1) A cleaner interface for the caller It's often appropriate to have a more abstract interface than the one provided by MAKE-INSTANCE. Providing a constructor as the documented inter-module interface for making a particular kind of object encourages users of the interface to think in more abstract, conceptual terms. Using a constructor also allows more aspects of the implementation to be changed without changing the interface: the class name and initarg names could be changed, or the data representation could be changed to a DEFSTRUCT representation or a standard-type, without changing the interface. The constructor could even be replaced by an interface function that does some complex computations to decide what type of object to create, or to decide whether to return an existing object or create a new one. These needs could be met simply by defining constructor functions with DEFUN and advertising them. Some reasons to have a :CONSTRUCTOR option in DEFCLASS are - to make it easier and more convenient for users to create constructors - to be culturally consistent with DEFSTRUCT - :CONSTRUCTOR is a convenient abbreviation for something you could do yourself in a more long-winded way, just like :ACCESSOR Other reasons appear below. (2) Coordination with class redefinition As the bridge between an external interface and the internal structure of a class, a constructor function contains certain information about the class, such as what are its initargs and their default values. When a class is redefined, any constructors for the class and its subclasses should be updated if necessary to keep them consistent with the class. Making this updating automatic is a convenience for programmers, so they don't have to remember to do it by hand. One way to make the updating automatic would be to add a new feature to the programming environment by which a linkage could be established between a function and a class so that redefining the class makes some edits to the source of the function and then recompiles it. A much simpler way is to make the constructor syntactically part of the DEFCLASS, so it naturally gets updated at the same time as the rest of the DEFCLASS. This is another way in which constructors are analogous to accessors. (3) More efficient than MAKE-INSTANCE MAKE-INSTANCE must operate by interpreting data structures that describe the class, while constructors can be compiled, since they know the exact class that they are constructing, and since they can be automatically recompiled if the class or any of its superclasses changes. Initialization methods can be completely inlined into a constructor, where MAKE-INSTANCE has to go through a generic function dispatch. Constructors can take positional arguments, which are more efficient in most implementations, while MAKE-INSTANCE requires keyword arguments. Gregor has argued that calls to MAKE-INSTANCE with a constant first argument can be equally optimized, since the exact class being constructed is known. While this is true in theory, it seems that either a complicated mechanism would be needed to make sure that the function was recompiled when the class was redefined in a way that invalidated the inline code, or else there would have to be user-visible declarations to control the tradeoff between performance and robustness in the face of class redefinition. Alternatively, calls to MAKE-INSTANCE with a constant first argument could be turned into calls to a constructor function that was created behind the scenes. Then if the class was redefined, only the constructor function would have to be recompiled. In either case, if we are going to have this type of mechanism, I would much rather make it explicitly visible as a :CONSTRUCTOR option than have it operating behind the scenes in some vaguely defined way. WHY GET RID OF CONSTRUCTORS? (1) Simplicity If we have both constructors and MAKE-INSTANCE, then we have two ways to do the same thing. [But CLOS very often provides both a primitive mechanism and a convenient abbreviation for a common case of using that mechanism.] The rules for mapping constructor parameter names into slots and initargs are complicated and confusing. [Very true. In this proposal they have been enormously simplified.] (2) Avoid hiding mechanisms Constructors contain a hidden performance optimization, in that there is more inlining in their bodies than can be achieved through documented mechanisms elsewhere. [I argued above that this is preferable to the inherent complexity of making that mechanism generally available. Of course there is nothing to stop us from documenting it if that's what we really want. Also, exactly the same thing could be said about :ACCESSOR, at least in the Symbolics implementation.] (3) Not more efficient than MAKE-INSTANCE (see discussion above) SYNTAX The DEFCLASS option (:CONSTRUCTOR -symbol-) creates a function named -symbol- that takes the initargs of this class as keyword arguments and returns an instance of this class. Thus a call to -symbol- looks just like a call to MAKE-INSTANCE with the first argument omitted. The DEFCLASS option (:CONSTRUCTOR -symbol- -constructor-lambda-list-) creates a function named -symbol- whose lambda-list is -constructor-lambda-list-. The function returns an instance of this class, initialized according to the parameters in -constructor-lambda-list-. Each parameter supplies the value of one initarg, determined by the following rules: - If a parameter variable name is EQ to an initarg name, the parameter supplies the value of that initarg. - If a parameter variable name is not EQ to any initarg name, but the symbol in the keyword package with the same name as the parameter variable name is EQ to an initarg name, the parameter supplies the value of that initarg. - If neither rule succeeds, signal an error. The second rule exists because initarg names are often keyword symbols, which are not valid as variable names. -constructor-lambda-list- allows all of the standard lambda-list features that DEFUN allows. The only difference is that if no initform is specified for an &optional, &key, or &aux parameter, instead of just defaulting to NIL, the parameter defaults in a special way, as in DEFSTRUCT constructors. An &optional or &key parameter with no initform defaults to the corresponding initarg's default-initarg form, or if there is none defaults to NIL but is not passed to initialization methods if unsupplied. An &aux parameter with no initform defaults to NIL but always behaves as if unsupplied: the corresponding initarg is not passed to initialization methods and if there is a default-initarg form, it is never evaluated. (This feature comes from DEFSTRUCT. Since &aux was never used in constructors in the Flavors programs I surveyed, I wouldn't propose it if DEFSTRUCT hadn't already introduced it into Common Lisp.) The :CONSTRUCTOR option can appear more than once in a DEFCLASS form. PROCEDURAL DEFINITION OF CONSTRUCTORS After receiving and defaulting its arguments, a constructor forms an initarg list from its parameters and calls MAKE-INSTANCE with the appropriate class object as the first argument and the initarg list as the remaining arguments. The actual code compiled for a constructor can be optimized in implementation-dependent ways, as long as it has the same effect as above. For example, instead of calling MAKE-INSTANCE, the constructor can inline the body of MAKE-INSTANCE and the bodies of some or all of the methods that MAKE-INSTANCE calls. This implies that the initarg list might not be fully materialized, parameter values might really be stored directly into slots, and keyword argument processing might be completely eliminated. Any optimization of this type is valid as long as the same effect as calling MAKE-INSTANCE is achieved and the compiled code is updated when the class or a superclass is redefined or a relevant method is added or removed. WHEN ARE CONSTRUCTORS DEFINED AND REDEFINED? A constructor for a class C cannot be accurately defined until each of C and its superclasses is defined and all applicable INITIALIZE-INSTANCE and ALLOCATE-INSTANCE methods have been defined. Until then, the set of initargs and default-initarg forms is not known. The macro-expansion of DEFCLASS includes a DEFUN for each constructor based on the information available at the time DEFCLASS is expanded. If any superclass is not yet defined, this constructor is a dummy that simply signals an error. At any later time when C is redefined, a superclass of C is defined or redefined, or a relevant method is added or removed, CLOS considers each constructor for C and if necessary recompiles it. If a class is redefined and a :CONSTRUCTOR is removed, FMAKUNBOUND is applied to the former constructor's name. Thus a constructor is always up to date with the latest information about its class. Note that a user might extract the constructor function from the function definition of its name, redefine the class (thus redefining the constructor), and then call the out of date constructor function. Implementations should be robust in the face of this, either signalling an error when an out of date constructor function is called, automatically calling the latest version of the constructor function, or making an instance of the class as it used to be defined and then updating it as if the class had been redefined after the instance was made. This follows from the principle that optimization of a constructor function should not affect its semantics. This is better than the way Flavors does it, which involves only creating constructors in COMPILE-FLAVOR-METHODS. PRIMITIVES FOR MAKING CONSTRUCTORS At the meta-object level, there will be primitive functions for turning a constructor lambda-list into a function by filling in parameter defaults and computing the function body, verifying that a constructor is still valid, and establishing and removing the linkage between a class and a constructor. A default method for some function that gets called when things are redefined will call these functions, to keep the constructors up to date. Very roughly, these will be: MAKE-CONSTRUCTOR class name &optional constructor-option-second-argument -> lambda-expression form To install the constructor function, evaluate (PROGN (SETF (SYMBOL-FUNCTION 'name) #'lambda-expression) form (LINK-CONSTRUCTOR 'class 'name T) 'name) VERIFY-CONSTRUCTOR class name &optional constructor-option-second-argument -> Boolean LINK-CONSTRUCTOR class name on-or-off We could also expose the next level down, which defines how class and constructor-option-second-argument are turned into information that is compared by VERIFY-CONSTRUCTOR to see whether the constructor needs to be regenerated, and defines how the form returned by MAKE-CONSTRUCTOR as its second value records this information. (This form is a bit of a crock. In the Symbolics system, it isn't necessary, because all information is in the lambda-expression and in the compiled-function object compiled from it. However, I'm assuming that some implementations cannot do this, and therefore provision is needed to associate this information with the name of the constructor rather than with the actual function object. If we can get rid of this, great. Of course LINK-CONSTRUCTOR still needs the name so class redefinition knows where to store the updated constructor.)  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 12:52:04 EDT Received: from Catawba.ms by ArpaGateway.ms ; 30 SEP 87 09:05:06 PDT Return-Path: Redistributed: CommonLoops.PA Received: from hplabs.HP.COM ([15.255.16.7]) by Xerox.COM ; 30 SEP 87 09:03:31 PDT Received: from hplms2 by hplabs.HP.COM with SMTP ; Wed, 30 Sep 87 09:01:59 PDT Received: from hplabsz.hpl.hp.com by hplms2; Wed, 30 Sep 87 09:01:42 pdt Return-Path: Received: from hplabsz by hplabsz; Wed, 30 Sep 87 10:02:39 pdt To: Rick.Busdiecker@cs.cmu.edu Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug X-Mailer: mh6.5 In-Reply-To: Your message of 30 Sep 87 11:10:00 -0400. <560013020/rfb@H.GP.CS.CMU.EDU> Date: Wed, 30 Sep 87 10:02:36 MST Message-Id: <6898.560016156@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > I think that that makes with-slots into a truly dangerous form. > Code that uses with-slots without the :prefix can be broken by adding a > slot to the class definition. That's true whether or not the :prefix option is there, and whether or not you use WITH-SLOTS or the accessor function directly. If you delete a slot (for example) the accessor function is undefined, so any method using the accessor function will break. Similarly, if you delete a slot even using the :PREFIX option, the code within the WITH-SLOTS would need to be changed, otherwise it will break when you try to reference the slot next time (precisely, a call to SLOT-MISSING will occur). Jim Kempf kempf@hplabs.hp.com  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 11:32:07 EDT Received: from Burger.ms by ArpaGateway.ms ; 30 SEP 87 08:14:01 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 30 SEP 87 08:11:51 PDT Date: 30 Sep 87 11:10 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <560013020/rfb@H.GP.CS.CMU.EDU> Why? Is there some benefit that out-weighs the added verbosity? Yes, because these options had to call intern in order to work, and there we a number of problems about what package the constructed symbol should be interned in. The 3 proposed solutions all had problems. Specifically: * intern the new symbols in the value of *package* at the time the defclass form is processed. - this is problematic because *package* is a special variable and under certain circumstances this can lead to surprising behavior I would think that the correct Common Lisp way to deal with the question would be to handle it the same way that defstruct handles conc-name. This first proposal seems like the right way to go. Are the certain circumstances that you mention also problematic for defstruct, or are the problems unique to defclass? Note that we also got rid of the :prefix option to with-slots for basically the same set of reasons. I think that that makes with-slots into a truly dangerous form. Code that uses with-slots without the :prefix can be broken by adding a slot to the class definition. Rick  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 30 Sep 87 01:25:21 EDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 22:02:37 PDT Date: 29 Sep 87 22:00 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug In-reply-to: Rick.Busdiecker@H.GP.CS.CMU.EDU's message of 29 Sep 87 18:20 EDT To: Rick.Busdiecker@cs.cmu.edu cc: CommonLoops.PA@Xerox.COM Message-ID: <870929-220237-1512@Xerox> From: Rick.Busdiecker@H.GP.CS.CMU.EDU Date: 29 Sep 87 12:20 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug NOTE: we decided last week to remove the :accessor-prefix and :reader-prefix options from defclass. This means that you will have to start using just :accessor and :reader. Why? Is there some benefit that out-weighs the added verbosity? Yes, because these options had to call intern in order to work, and there we a number of problems about what package the constructed symbol should be interned in. The 3 proposed solutions all had problems. Specifically: * intern the new symbols in the value of *package* at the time the defclass form is processed. - this is problematic because *package* is a special variable and under certain circumstances this can lead to surprising behavior * intern the new symbols in the package of the slot-name - this is often not what you want. If you have a slot named list, and a prefix of foo-, and your program is in your own package, you probably want the symbol to be my-package::foo-list not lisp::foo-list * intern the symbols in the package of the prefix symbol - often, this is likely to solve the problem presented in the second bullet, but it won't work in general and is kind of a crock. Note that we also got rid of the :prefix option to with-slots for basically the same set of reasons.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 22:57:52 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:44:41 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244645; Tue 29-Sep-87 22:45:30 EDT Date: Tue, 29 Sep 87 22:45 EDT From: David A. Moon Subject: Re: Redefining Classes To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <2768937098-6088589@Jenner> Message-ID: <870929224517.0.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Tue, 29 Sep 87 16:11:38 CDT From: Patrick H Dussud Date: Mon, 28 Sep 87 22:18 EDT From: "David A. Moon" For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same reasons? This is not a problem. Since at least March, CHANGE-CLASS has been documented to convey the slot values before it calls CLASS-CHANGED. One inconsistency remains: CHANGE-CLASS initializes the newly added slots from their initforms before calling CLASS-CHANGED, whereas class redefinition initializes the newly added slots in the default primary method for UPDATE-OBSOLETE-INSTANCE, last I heard. We probably ought to make them both work the same way. I prefer not to put this into a method, because then we have to say what is the state of those slots when a :BEFORE method is running. I prefer to have the instance in a completely consistent state before the user-specializable generic function is called. Others prefer to put it into a method so it can be replaced with something else. Is that something people actually would do?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 22:52:14 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:39:03 PDT Received: from relay2.cs.net by RELAY.CS.NET id aa11959; 29 Sep 87 20:18 EDT Received: from csl.ti.com by RELAY.CS.NET id ap14445; 29 Sep 87 20:01 EDT Received: from dsg by tilde id AA17961; Tue, 29 Sep 87 17:24:06 CDT Received: From Jenner By dsg Via TCP With SMTP; Tue, 29 Sep 87 14:44:31 CDT Message-Id: <2768931638-5760531@Jenner> Date: Tue, 29 Sep 87 14:40:38 CDT From: Patrick H Dussud To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: Revised draft of object creation proposal In-Reply-To: Msg of Mon, 28 Sep 87 14:14 EDT from "David A. Moon" Date: Mon, 28 Sep 87 14:14 EDT From: "David A. Moon" Subject: Revised draft of object creation proposal This version differs from the previous one I mailed out only in some small corrections based on comments received in the mail. The terminology has been changed back from "named argument" to "keyword argument." It may be about time to start converting this to the text that will go into the specification document. Any more comments first? Looks OK to me. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 22:48:36 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:34:52 PDT Received: from relay2.cs.net by RELAY.CS.NET id ae11869; 29 Sep 87 20:12 EDT Received: from csl.ti.com by RELAY.CS.NET id af14445; 29 Sep 87 19:58 EDT Received: from dsg by tilde id AA17934; Tue, 29 Sep 87 17:23:19 CDT Received: From Jenner By dsg Via TCP With SMTP; Tue, 29 Sep 87 14:44:19 CDT Message-Id: <2768930774-5708656@Jenner> Date: Tue, 29 Sep 87 14:26:14 CDT From: Patrick H Dussud To: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Various Topics Discussed Last Week In-Reply-To: Msg of Mon, 28 Sep 87 17:05 EDT from "David A. Moon" Date: Mon, 28 Sep 87 17:05 EDT From: "David A. Moon" Subject: Various Topics Discussed Last Week Date: Mon, 28 Sep 87 09:42:29 MST From: kempf%hplabsz@hplabs.HP.COM 2) On blocks in methods: I agree that Alternative 1 would be best. Users who want something different can either use a :AROUND method, as Moon suggested, or program their own generic function dispatching function, using the metaobject protocol. Since we all seem to be agreed on this, I added the following to my clos-decisions file, which can be used as a resource to make sure we don't forget to document this decision: 2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded by an implicit block named -name-, if that is a symbol, or -name1-, if -name- is (SETF -name1-), by analogy with DEFUN. The same applies to methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET, GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around the body of a method defined by the :METHOD option to GENERIC-FUNCTION. Dissenters speak now. I agree with this. 7) On NEXT-METHODS: The primary reason is for being able to tell if calling CALL-NEXT-METHOD would signal an error. I understand Masinter's concern, and wonder if perhaps it might not be better to handle this with Ken Pitman's error proposal. Other than finding out whether a call to CALL-NEXT-METHOD is valid, there isn't much use for the list of next methods, as Masinter has pointed out. I have no real opinion on this, but we could change this to NEXT-METHOD, which returns the method object that CALL-NEXT-METHOD would call if there is one, and returns NIL if CALL-NEXT-METHOD would signal the no-more-methods error. Then we wouldn't have to worry about the implications of consing, rplac'ing, and looking at the list. I don't have objections to that, we could even make it a predicate, NEXT-METHOD-P returns T if there is a next method, and NIL otherwise. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 22:44:49 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 19:31:26 PDT Received: from relay2.cs.net by RELAY.CS.NET id ab11869; 29 Sep 87 20:11 EDT Received: from csl.ti.com by RELAY.CS.NET id aa14445; 29 Sep 87 19:57 EDT Received: from dsg by tilde id AA17433; Tue, 29 Sep 87 17:01:54 CDT Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Tue, 29 Sep 87 13:48:36 CDT Message-Id: <2768928327-5561620@Jenner> Date: Tue, 29 Sep 87 13:45:27 CDT From: Patrick H Dussud To: kempf%hplabsz@hplabs.hp.com Cc: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Exact type In-Reply-To: Msg of Mon, 28 Sep 87 13:54:27 MST from kempf%hplabsz@hplabs.hp.com Date: Mon, 28 Sep 87 13:54:27 MST From: kempf%hplabsz@hplabs.hp.com Subject: Re: Exact type >But allowing the other COMMON subtypes would makes programs non portable: >The list of subtypes of a type is implementation dependent. We say (page >1-14) that individual implementation can add additional subclass >relationships as long as they don't violate CLtL. But the subtype relationships in CLtL must still hold. Thus, any importabilities will be the result of importabilites in the Common Lisp type system, not in the CLOS addition. Reading the rules on pg. 33-35, it's difficult to discern importabilities, but, talking to Gregor (who has some experience in this area), they do exist. However, I think the place to address the problem is to tighten up the Common Lisp type system, not restrict EXACT-TYPE. I don't think it's a problem with the CLtL type system. Implementations can always specialize a built-in type without breaking the portability of program relying on TYPEP and SUBTYPEP. However it can break the portability of code relying on EXACT-TYPE. The user shouldn't expect that an argument will be exactly of this built-in type. On some machines, you cannot expect an cons cell argument to be always of the exact type CONS. While I don't particularly agree with this policy, I think that it gives implementations so much latitude already that restricting EXACT-TYPE would be inappropriate. My way of restricting EXACT-TYPE would prevent the user from expecting things he cannot always get. I still think EXACT-TYPE makes sense for user defined type though. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 21:32:47 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 18:20:06 PDT Received: from Salvador.ms by ArpaGateway.ms ; 29 SEP 87 18:08:32 PDT Date: 29 Sep 87 18:08 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Redefining Classes To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870929-180832-1165@Xerox> After reading Patrick's message, and some more thought, I now agree with Moon's paragraph. I am even willing to believe that common slots (retained slots) maintain their bit contents (unbound slots are not initialized by the updating). I have rewritten Moon's paragraph using Patrick's suggested name change: When redefining a class causes instances to be updated can be implementation-dependent. The user extendible generic function (update-instance-structure instance added-slot-names removed-slot-names removed-bound-slot-values) is called to complete updating of the instance structure; its primary method uses initforms to initialize the slots whose names are listed in added-slot-names. update-instance-structure is called no later than the first slot read or write of that instance after the class is redefined. The retained slot values are already in place when update-instance-structure is called. There is still the open problem of (re)initialization of class variables on redefinition. More thoughts??? Patrick asked: Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same reasons? I believe that update-instance-structure and class-changed should be comparable. I will send out a revised writeup. I agree with the general principle reiterated by Patrick, and strengthened here: No user should ever get hold of a value coming from a non-updated instance.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 29 Sep 87 20:52:08 EDT Received: from Burger.ms by ArpaGateway.ms ; 29 SEP 87 15:43:34 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 29 SEP 87 15:39:24 PDT Date: 29 Sep 87 18:20 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: Gregor.pa@Xerox.COM Cc: CommonLoops.PA@Xerox.COM Subject: Re: :accessor-prefix bug Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <559952459/rfb@H.GP.CS.CMU.EDU> Date: 29 Sep 87 12:20 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug NOTE: we decided last week to remove the :accessor-prefix and :reader-prefix options from defclass. This means that you will have to start using just :accessor and :reader. Why? Is there some benefit that out-weighs the added verbosity? Rick  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 20:49:41 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:32:48 PDT Received: from [128.89.1.80] by RELAY.CS.NET id ai10701; 29 Sep 87 18:14 EDT Received: from csl.ti.com by RELAY.CS.NET id ah13799; 29 Sep 87 18:00 EDT Received: from Jenner by tilde id AA15823; Tue, 29 Sep 87 16:13:41 CDT Message-Id: <2768937098-6088589@Jenner> Date: Tue, 29 Sep 87 16:11:38 CDT From: Patrick H Dussud To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: Redefining Classes In-Reply-To: Msg of Mon, 28 Sep 87 22:18 EDT from "David A. Moon" Date: Mon, 28 Sep 87 22:18 EDT From: "David A. Moon" Summary: When redefining a class causes instances to be updated can be implementation-dependent. (update-from-obsolete-instance instance added-slot-names removed-slot-names removed-bound-slot-values); the primary method uses initforms to initialize the slots whose names are listed in added-slot-names. update-from-obsolete-instance is called no later than the first slot read or write after the class is redefined. The retained slot values are already in place when update-from-obsolete-instance is called. Those are my opinions. I have two problems with [update-obsolete-instance]. The easy problem is that I don't like the name update-obsolete-instance, because the instance doesn't really seem obsolete to me. One idea is to take an analogy to class-changed and call it class-redefined. In Flavors we call it transform-instance, but it doesn't have quite the same semantics. It's likely that someone can think of a better name than any of these. We could call it update-from-obsolete-instance, or conform-instance-to-class. Since it takes ans instance as an argument, I don't like names like class-redefined -- which seems to focus on the class. Good point. update-from-obsolete-instance appeals to me, although it might be thought to imply that two instances are involved. We could call it update-instance-structure. We talked about the structure of an instance being changed in the writeup. Much more important, I can't implement the specification that the slots are initially uninitialized and then they are filled in from values saved in a property list. There are two problems, one obvious and one subtle. The obvious problem involves slots that were unbound originally; since there is no Lisp value that means "unbound", there is nothing that can be put into the property list for these slots. But if we don't put any entry in the property list, then the desired feature that the method can tell which slots were added or removed is lost; these slots look like they were added, even though they weren't. We could designate such a value (make it be the value of a globally accessible variable). Then putting such a value in a slot would be equivalent to making it unbound. I can hear the ARGHHH from here, but it does make accessible something that we are having to make programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste (and I could be convinced on this fairly easily), why is it you could not implement this -- is there a particular tradeoff that you are not being explicit about? It doesn't work to have a magic Lisp object that means "unbound" when it's the value of a slot, because then you can never talk about that value in any way that involves putting it into a slot. If you think that's a matter of taste, the other answer is that my hardware has the unbound slot value built into it, and it would cost me a couple million dollars to change it. Here we have both the rarified philosophical argument and the businesslike pragmatic argument. As Moon says, "unbound" is a value, but not a lisp object. I would oppose a proposal saying that we can pass it around and storing it into a slot. Note that SLOT-MAKUNBOUND would not implemented using CLtL primitives, but lower level ones that don't see lisp objects but bits. To my way of thinking it is philosophically inconsistent to have different rules for whether a slot's value is changed when the class is redefined, depending on slot-boundp. At this level, "unbound" should be treated like just another value. I hope you don't think this is too inconsistent with what I said just above: "unbound" is a slot value, but it is not a Lisp object. I think it's better to do things like filling in previously unbound slots in old instances with update-from-obsolete-instance (or whatever name we choose) methods. I agree. If you want to reinitialize some slot, modify the method for "update-from-obsolete-instance (or whatever name we choose)" and call MAKE-INSTANCES-OBSOLETE. The subtle problem involves some language extensions that we have, allowing slots to have contents that cannot be expressed as Lisp values in a property list. For instance, there is a mechanism similar to Prolog logic-variables which allows two slots to be linked together. This linkage has to be preserved in the face of class redefinition. Can such linked values only be used inside of objects, and not within lists? I though inivisible pointers can be used anywhere. I don't understand what the assumptions underlying this extension are. They can be used in lists, but the point is that care needs to be exercised when moving them around. The net effect is that the code that moves slot values from one piece of memory to another, when an instance has to have new memory allocated for it, can't be written portably in our system. But I don't see why anyone would want a portable version of it. I hadn't though of that. This is true, we must preserve those structures. The problem is the same as with unbound slots, invisible pointers are not lisp objects. For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same reasons? Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. We're going to have to specify this a little more precisely, I suspect. We should specify when is the latest time that an implementation can call update-obsolete-instance, and then say that it is permitted to call it any time earlier (after the class has been redefined). I now believe that the latest time can simply be the time any of the four slot access and modification functions (or internal equivalent) is called, in spite of all the flaming against this we engaged in while discussing Danny's proposal at the meeting last week. Agreed. I'd like to hear Patrick's opinion on this timing issue before I have much confidence that we have figured it out. It's OK with me. It is important that all the metaclass primitive that we specify have to work the same way. The meta-user should not get hold of a value coming from a non-updated instance. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 20:47:36 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:33:18 PDT Received: from [128.89.1.80] by RELAY.CS.NET id al10701; 29 Sep 87 18:15 EDT Received: from csl.ti.com by RELAY.CS.NET id aj13799; 29 Sep 87 18:02 EDT Received: from Jenner by tilde id AA15864; Tue, 29 Sep 87 16:14:49 CDT Message-Id: <2768937166-6092662@Jenner> Date: Tue, 29 Sep 87 16:12:46 CDT From: Patrick H Dussud To: kempf%hplabsz@hplabs.hp.com Cc: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Exact type In-Reply-To: Msg of Mon, 28 Sep 87 13:54:27 MST from kempf%hplabsz@hplabs.hp.com Date: Mon, 28 Sep 87 13:54:27 MST From: kempf%hplabsz@hplabs.hp.com Subject: Re: Exact type >But allowing the other COMMON subtypes would makes programs non portable: >The list of subtypes of a type is implementation dependent. We say (page >1-14) that individual implementation can add additional subclass >relationships as long as they don't violate CLtL. But the subtype relationships in CLtL must still hold. Thus, any importabilities will be the result of importabilites in the Common Lisp type system, not in the CLOS addition. Reading the rules on pg. 33-35, it's difficult to discern importabilities, but, talking to Gregor (who has some experience in this area), they do exist. However, I think the place to address the problem is to tighten up the Common Lisp type system, not restrict EXACT-TYPE. I don't think it's a problem with the CLtL type system. Implementations can always specialize a built-in type without breaking the portability of program relying on TYPEP and SUBTYPEP. However it can break the portability of code relying on EXACT-TYPE. The user shouldn't expect that an argument will be exactly of this built-in type. On some machines, you cannot expect an cons cell argument to be always of the exact type CONS. While I don't particularly agree with this policy, I think that it gives implementations so much latitude already that restricting EXACT-TYPE would be inappropriate. My way of restricting EXACT-TYPE would prevent the user from expecting things he cannot always get. I still think EXACT-TYPE makes sense for user defined type though. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 20:45:57 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 17:32:24 PDT Received: from [128.89.1.80] by RELAY.CS.NET id ak10701; 29 Sep 87 18:14 EDT Received: from csl.ti.com by RELAY.CS.NET id ai13799; 29 Sep 87 18:01 EDT Received: from Jenner by tilde id AA15847; Tue, 29 Sep 87 16:14:20 CDT Message-Id: <2768937138-6091027@Jenner> Date: Tue, 29 Sep 87 16:12:18 CDT From: Patrick H Dussud To: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Various Topics Discussed Last Week In-Reply-To: Msg of Mon, 28 Sep 87 17:05 EDT from "David A. Moon" Date: Mon, 28 Sep 87 17:05 EDT From: "David A. Moon" Subject: Various Topics Discussed Last Week Date: Mon, 28 Sep 87 09:42:29 MST From: kempf%hplabsz@hplabs.HP.COM 2) On blocks in methods: I agree that Alternative 1 would be best. Users who want something different can either use a :AROUND method, as Moon suggested, or program their own generic function dispatching function, using the metaobject protocol. Since we all seem to be agreed on this, I added the following to my clos-decisions file, which can be used as a resource to make sure we don't forget to document this decision: 2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded by an implicit block named -name-, if that is a symbol, or -name1-, if -name- is (SETF -name1-), by analogy with DEFUN. The same applies to methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET, GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around the body of a method defined by the :METHOD option to GENERIC-FUNCTION. Dissenters speak now. I agree with this. 7) On NEXT-METHODS: The primary reason is for being able to tell if calling CALL-NEXT-METHOD would signal an error. I understand Masinter's concern, and wonder if perhaps it might not be better to handle this with Ken Pitman's error proposal. Other than finding out whether a call to CALL-NEXT-METHOD is valid, there isn't much use for the list of next methods, as Masinter has pointed out. I have no real opinion on this, but we could change this to NEXT-METHOD, which returns the method object that CALL-NEXT-METHOD would call if there is one, and returns NIL if CALL-NEXT-METHOD would signal the no-more-methods error. Then we wouldn't have to worry about the implications of consing, rplac'ing, and looking at the list. I don't have objections to that, we could even make it a predicate, NEXT-METHOD-P returns T if there is a next method, and NIL otherwise. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 19:43:06 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Sep 87 16:24:44 PDT Received: from relay2.cs.net by RELAY.CS.NET id aa10877; 29 Sep 87 18:30 EDT Received: from csl.ti.com by RELAY.CS.NET id av13799; 29 Sep 87 18:12 EDT Received: from dsg by tilde id AA17297; Tue, 29 Sep 87 16:55:49 CDT Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Tue, 29 Sep 87 12:25:56 CDT Message-Id: <2768923341-5262035@Jenner> Date: Tue, 29 Sep 87 12:22:21 CDT From: Patrick H Dussud To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: Redefining Classes In-Reply-To: Msg of Mon, 28 Sep 87 22:18 EDT from "David A. Moon" Date: Mon, 28 Sep 87 22:18 EDT From: "David A. Moon" Summary: When redefining a class causes instances to be updated can be implementation-dependent. (update-from-obsolete-instance instance added-slot-names removed-slot-names removed-bound-slot-values); the primary method uses initforms to initialize the slots whose names are listed in added-slot-names. update-from-obsolete-instance is called no later than the first slot read or write after the class is redefined. The retained slot values are already in place when update-from-obsolete-instance is called. Those are my opinions. I have two problems with [update-obsolete-instance]. The easy problem is that I don't like the name update-obsolete-instance, because the instance doesn't really seem obsolete to me. One idea is to take an analogy to class-changed and call it class-redefined. In Flavors we call it transform-instance, but it doesn't have quite the same semantics. It's likely that someone can think of a better name than any of these. We could call it update-from-obsolete-instance, or conform-instance-to-class. Since it takes ans instance as an argument, I don't like names like class-redefined -- which seems to focus on the class. Good point. update-from-obsolete-instance appeals to me, although it might be thought to imply that two instances are involved. We could call it update-instance-structure. We talked about the structure of an instance being changed in the writeup. Much more important, I can't implement the specification that the slots are initially uninitialized and then they are filled in from values saved in a property list. There are two problems, one obvious and one subtle. The obvious problem involves slots that were unbound originally; since there is no Lisp value that means "unbound", there is nothing that can be put into the property list for these slots. But if we don't put any entry in the property list, then the desired feature that the method can tell which slots were added or removed is lost; these slots look like they were added, even though they weren't. We could designate such a value (make it be the value of a globally accessible variable). Then putting such a value in a slot would be equivalent to making it unbound. I can hear the ARGHHH from here, but it does make accessible something that we are having to make programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste (and I could be convinced on this fairly easily), why is it you could not implement this -- is there a particular tradeoff that you are not being explicit about? It doesn't work to have a magic Lisp object that means "unbound" when it's the value of a slot, because then you can never talk about that value in any way that involves putting it into a slot. If you think that's a matter of taste, the other answer is that my hardware has the unbound slot value built into it, and it would cost me a couple million dollars to change it. Here we have both the rarified philosophical argument and the businesslike pragmatic argument. As Moon says, "unbound" is a value, but not a lisp object. I would oppose a proposal saying that we can pass it around and storing it into a slot. Note that SLOT-MAKUNBOUND would not implemented using CLtL primitives, but lower level ones that don't see lisp objects but bits. To my way of thinking it is philosophically inconsistent to have different rules for whether a slot's value is changed when the class is redefined, depending on slot-boundp. At this level, "unbound" should be treated like just another value. I hope you don't think this is too inconsistent with what I said just above: "unbound" is a slot value, but it is not a Lisp object. I think it's better to do things like filling in previously unbound slots in old instances with update-from-obsolete-instance (or whatever name we choose) methods. I agree. If you want to reinitialize some slot, modify the method for "update-from-obsolete-instance (or whatever name we choose)" and call MAKE-INSTANCES-OBSOLETE. The subtle problem involves some language extensions that we have, allowing slots to have contents that cannot be expressed as Lisp values in a property list. For instance, there is a mechanism similar to Prolog logic-variables which allows two slots to be linked together. This linkage has to be preserved in the face of class redefinition. Can such linked values only be used inside of objects, and not within lists? I though inivisible pointers can be used anywhere. I don't understand what the assumptions underlying this extension are. They can be used in lists, but the point is that care needs to be exercised when moving them around. The net effect is that the code that moves slot values from one piece of memory to another, when an instance has to have new memory allocated for it, can't be written portably in our system. But I don't see why anyone would want a portable version of it. I hadn't though of that. This is true, we must preserve those structures. The problem is the same as with unbound slots, invisible pointers are not lisp objects. For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Shouldn't CHANGE-CLASS & CLASS-CHANGED changed the same way for the same reasons? Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. We're going to have to specify this a little more precisely, I suspect. We should specify when is the latest time that an implementation can call update-obsolete-instance, and then say that it is permitted to call it any time earlier (after the class has been redefined). I now believe that the latest time can simply be the time any of the four slot access and modification functions (or internal equivalent) is called, in spite of all the flaming against this we engaged in while discussing Danny's proposal at the meeting last week. Agreed. I'd like to hear Patrick's opinion on this timing issue before I have much confidence that we have figured it out. It's OK with me. It is important that all the metaclass primitive that we specify have to work the same way. The meta-user should not get hold of a value coming from a non-updated instance. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 18:44:12 EDT Date: 29 Sep 87 1529 PDT From: Dick Gabriel Subject: Various Decisions To: Common-lisp-object-system@SAIL.STANFORD.EDU On condition handlers instead of NEXT-METHOD: It seems that condition handlers are an appropriate vehicle for dealing with exceptional conditions, or at least with conditions that are not routinely encountered. For example, in a Lisp in which CAR and CDR of NIL signal errors, one would be surprised to see the naive SUBST function written like this: (defun subst (x y z) (cond ((eq x z) y) (t (cons (subst x y (car z)) (subst x y (cdr z)))))) with condition handlers for the null and non-CONS cases. Similarly, if it is the case (and I think it likely) that a programmer frequently wants to CALL-NEXT-METHOD when there might not be one, then he will likely want to write: (when (next-method) (call-next-method)) or use a non-error-signaling version of CALL-NEXT-METHOD rather than program a condition handler. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 18:27:20 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 15:13:42 PDT Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 15:10:55 pdt Return-Path: Received: from hplabsz by hplabsz; Tue, 29 Sep 87 16:11:52 pdt To: "David A. Moon" Cc: Pavel.pa@Xerox.COM, Common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: Various Decisions X-Mailer: mh6.5 In-Reply-To: Your message of Tue, 29 Sep 87 17:36:00 -0400. <870929173603.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Tue, 29 Sep 87 16:11:46 MST Message-Id: <3966.559951906@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Date: Tue, 29 Sep 87 12:05:58 PDT > From: Pavel.pa@Xerox.COM > Why are folks so opposed to using the error system instead of this > NEXT-METHOD function? It seems the obvious thing, leading to more > readable code with a clearer intent. > Note that condition h> andlers have dynamic rather than lexical "scope" > (or whatever word you want to use for the portion of program that they > affect). Thus a HANDLER-CASE around a CALL-NEXT-METHOD might actually > intercept some inner CALL-NEXT-METHOD in some inner, nested method. > There's no way to turn off the handler as soon as the CALL-NEXT-METHOD > has succeeded in passing control to the next method. Well, my reading of the Pitman error proposal (admittedly dated 1985) is that something like this should work: (catch-condition no-next-method &body (call-next-method)) should work. If there is no next method, then NIL will be returned as the first value of the form, and the condition "object" as the second. Of course, the condition NO-NEXT-METHOD must first be defined.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 17:56:55 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:43:53 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244370; Tue 29-Sep-87 17:35:57 EDT Date: Tue, 29 Sep 87 17:36 EDT From: David A. Moon Subject: Re: Various Decisions To: Pavel.pa@Xerox.COM cc: Common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870929-120601-2316@Xerox> Message-ID: <870929173603.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Line-fold: No Date: Tue, 29 Sep 87 12:05:58 PDT From: Pavel.pa@Xerox.COM Why are folks so opposed to using the error system instead of this NEXT-METHOD function? It seems the obvious thing, leading to more readable code with a clearer intent. Note that condition handlers have dynamic rather than lexical "scope" (or whatever word you want to use for the portion of program that they affect). Thus a HANDLER-CASE around a CALL-NEXT-METHOD might actually intercept some inner CALL-NEXT-METHOD in some inner, nested method. There's no way to turn off the handler as soon as the CALL-NEXT-METHOD has succeeded in passing control to the next method.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 17:54:10 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:40:38 PDT Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 14:37:35 pdt Return-Path: Received: from hplabsz by hplabsz; Tue, 29 Sep 87 15:38:33 pdt To: "David A. Moon" Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: Status of CLOS decisions X-Mailer: mh6.5 In-Reply-To: Your message of Tue, 22 Sep 87 23:07:00 -0400. <870922230752.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Tue, 29 Sep 87 15:38:31 MST Message-Id: <3388.559949911@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > REVISED ``INHERITANCE OF SLOTS AND SLOT OPTIONS'' SECTION: This looks good to me, with the proviso that "shared slot" be replaced by whatever terminology we decide on. After reading through it, I can't find any ambiguity in the wording. The reference to :DYNAMIC slots needs to be removed, however. It seems to be more concise than the current description.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 17:28:29 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 14:15:01 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 12:06:01 PDT Date: Tue, 29 Sep 87 12:05:58 PDT From: Pavel.pa@Xerox.COM Subject: Re: Various Decisions In-reply-to: <870929-104035-2118@Xerox> To: Common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870929-120601-2316@Xerox> Why are folks so opposed to using the error system instead of this NEXT-METHOD function? It seems the obvious thing, leading to more readable code with a clearer intent. Pavel  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 29 Sep 87 16:25:25 EDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 13:14:56 PDT Date: 29 Sep 87 13:13 PDT From: Gregor.pa@Xerox.COM Subject: Re: load-time compilation In-reply-to: Rick.Busdiecker@H.GP.CS.CMU.EDU's message of 29 Sep 87 14:05 EDT To: Rick.Busdiecker@cs.cmu.edu cc: CommonLoops.PA@Xerox.COM Message-ID: <870929-131456-2460@Xerox> There are other times when load time compilation happens. If for example you define a generic function whose lambda list congruence is 'unlike' any generic function in the 'loadup' the compiler will be invoked. Most people will never see this since PCL pre-defines a lot of possible conguences. But some will see this occaisonal calling of the compiler. The next release of PCL will still have this problem since it isn't too crippling for anyone.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 29 Sep 87 16:25:10 EDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 12:22:59 PDT Date: 29 Sep 87 12:20 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug In-reply-to: Warren Harris 's message of Tue, 22 Sep 87 13:24:12 PDT To: harris%hplwhh@hplabs.HP.COM cc: commonloops.pa@Xerox.COM, kempf%hplwhh@hplabs.HP.COM, dsouza%hplwhh@hplabs.HP.COM Message-ID: <870929-122259-2343@Xerox> I have uncovered what seems to me to be a bug with :accessor-prefix. For example: (defclass foo () ((this :initform 'a)) (:accessor-prefix nil)) (defmethod-setf this ((f foo)) (x) (print 'here) (setf (slot-value f 'this) x)) (defclass bar (foo) ((this :initform 'b) ; simply define a new initial value (that :initform 'c)) (:accessor-prefix nil)) In class FOO I use :accessor-prefix to generate the THIS and SETF-THIS methods. The SETF-THIS method is then specialized. In class BAR :accessor-prefix is supposed to define THAT and SETF-THAT methods, and allow the THIS and specialized SETF-THIS methods to be inherited. It however seems to redefine the SETF-THIS method: The defclass for the class BAR clearly requests that methods for THIS setf-THIS THAT and setf-THAT be created. The use of :accessor-prefix nil says generate methods for all the slots. So there is no bug here. Probably what you should be doing is: (defclass bar (foo) ((this :initform 'b) ; simply define a new initial value (that :initform 'c :accessor that)) ) Then you would get the behavior you want. NOTE: we decided last week to remove the :accessor-prefix and :reader-prefix options from defclass. This means that you will have to start using just :accessor and :reader. Sorry for the delay in answering this message.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 29 Sep 87 16:24:59 EDT Received: from Catawba.ms by ArpaGateway.ms ; 29 SEP 87 11:16:55 PDT Return-Path: Redistributed: CommonLoops.PA Received: from H.GP.CS.CMU.EDU by Xerox.COM ; 29 SEP 87 11:13:49 PDT Date: 29 Sep 87 14:05 EDT From: Rick.Busdiecker@H.GP.CS.CMU.EDU To: CommonLoops.PA@Xerox.COM Subject: load-time compilation Reply-To: Rick.Busdiecker@cs.cmu.edu Message-Id: <559937122/rfb@H.GP.CS.CMU.EDU> This message refers to the version of PCL/CLOS whose *pcl-system-date* is "8/27/87 August 27th, 1987". The only load-time compilation which I've noticed is for class constructor functions created for the :CONSTRUCTOR class option to DEFCLASS. Are there other places where load-time compilation occurs? Is the next release expected to be free of load-time compilation? Rick  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 16:15:08 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 12:59:54 PDT Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 12:59:06 pdt Return-Path: Received: from hplabsz by hplabsz; Tue, 29 Sep 87 14:00:02 pdt To: Danny Bobrow Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: Shared/local;class/instance X-Mailer: mh6.5 In-Reply-To: Your message of 29 Sep 87 10:29:00 -0700. <870929-102940-2073@Xerox> Date: Tue, 29 Sep 87 13:59:58 MST Message-Id: <2048.559943998@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Therefore, I simply believe that :shared is a better name than > :class in terms of being intuitive. > The issue is what the pair of names should be; instance/class or > local/shared. I have argued on the basis of possible extensions that > we should use :instance and :class. Another argument is that instance > and class are used in Smalltalk with the same me> anings. Hence people > who take a course in object oriented programming using Smalltalk will > not have to learn yet another isomorphic terminology. Danny has made a good point. Compatibility with Smalltalk will make skill transferance easier.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 15:35:38 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Sep 87 12:22:18 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 244218; Tue 29-Sep-87 15:23:13 EDT Date: Tue, 29 Sep 87 15:23 EDT From: David A. Moon Subject: Re: Various Decisions To: Common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870929-104035-2118@Xerox> Message-ID: <870929152320.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 29 Sep 87 10:40 PDT From: Danny Bobrow On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential confusion that RPLACD might cause for users. I don't care. Remember that NEXT-METHODS was introduced first as an improvement over call-next-method-or-nil. Hence its primary purpose was to allow a programmer to avoid using call-next-method when it would signal an error. NEXT-METHOD satisfies that goal. Question: Is there anything else we want to make available at run time? If we are only getting the next method, perhaps we ought to only have NEXT-METHOD-P which returns T or NIL; this might allow some optimizations of the combined code. Okay, here's what I have written down about this topic now: The function NEXT-METHODS was added in September. It is scoped the same as CALL-NEXT-METHOD, takes no arguments, and returns a list of method objects, of which the first is the one that CALL-NEXT-METHOD calls. The effect of modifying the list is undefined. Moon and Gabriel like NEXT-METHOD better; it returns a method object or NIL. Kempf likes NEXT-METHOD better than NEXT-METHODS, but likes nothing even better, since CALL-NEXT-METHOD could signal a condition. Bobrow: NEXT-METHOD-P, returning no unnecessary information, is even better. Moon: I like that.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 15:04:52 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:50:16 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 10:40:35 PDT Date: 29 Sep 87 10:40 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Various Decisions In-reply-to: Dick Gabriel 's message of 29 Sep 87 09:28 PDT To: RPG@SAIL.STANFORD.EDU cc: Common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870929-104035-2118@Xerox> On the implicit block proposal, I agree with Moon's writeup. Fine with me. On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential confusion that RPLACD might cause for users. I don't care. Remember that NEXT-METHODS was introduced first as an improvement over call-next-method-or-nil. Hence its primary purpose was to allow a programmer to avoid using call-next-method when it would signal an error. NEXT-METHOD satisfies that goal. Question: Is there anything else we want to make available at run time? If we are only getting the next method, perhaps we ought to only have NEXT-METHOD-P which returns T or NIL; this might allow some optimizations of the combined code.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 15:03:50 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:49:57 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 10:29:40 PDT Date: 29 Sep 87 10:29 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Shared/local;class/instance In-reply-to: Dick Gabriel 's message of 28 Sep 87 18:36 PDT To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870929-102940-2073@Xerox> Therefore, I simply believe that :shared is a better name than :class in terms of being intuitive. The issue is what the pair of names should be; instance/class or local/shared. I have argued on the basis of possible extensions that we should use :instance and :class. Another argument is that instance and class are used in Smalltalk with the same meanings. Hence people who take a course in object oriented programming using Smalltalk will not have to learn yet another isomorphic terminology.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 14:40:31 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 11:24:18 PDT Received: from hplabsz.hpl.hp.com by hplms2; Tue, 29 Sep 87 11:24:13 pdt Return-Path: Received: from hplabsz by hplabsz; Tue, 29 Sep 87 12:25:11 pdt To: Dick Gabriel Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: Various Decisions X-Mailer: mh6.5 In-Reply-To: Your message of 29 Sep 87 09:28:00 -0700. Date: Tue, 29 Sep 87 12:25:07 MST Message-Id: <1122.559938307@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential > confusion that RPLACD might cause for users. I still think it would be better to just let this be handled by the error system, but NEXT-METHOD is better than NEXT-METHODS.  Received: from Xerox.COM (TCP 1200400040) by AI.AI.MIT.EDU 29 Sep 87 13:49:12 EDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 09:54:40 PDT Date: 29 Sep 87 09:52 PDT From: Gregor.pa@Xerox.COM Subject: Re: :accessor-prefix bug In-reply-to: Warren Harris 's message of Tue, 22 Sep 87 13:24:12 PDT To: harris%hplwhh@hplabs.HP.COM cc: commonloops.pa@Xerox.COM, kempf%hplwhh@hplabs.HP.COM, dsouza%hplwhh@hplabs.HP.COM Message-ID: <870929-095440-2022@Xerox> I have uncovered what seems to me to be a bug with :accessor-prefix. For example: (defclass foo () ((this :initform 'a)) (:accessor-prefix nil)) (defmethod-setf this ((f foo)) (x) (print 'here) (setf (slot-value f 'this) x)) (defclass bar (foo) ((this :initform 'b) ; simply define a new initial value (that :initform 'c)) (:accessor-prefix nil)) In class FOO I use :accessor-prefix to generate the THIS and SETF-THIS methods. The SETF-THIS method is then specialized. In class BAR :accessor-prefix is supposed to define THAT and SETF-THAT methods, and allow the THIS and specialized SETF-THIS methods to be inherited. It however seems to redefine the SETF-THIS method: The defclass for the class BAR clearly requests that methods for THIS setf-THIS THAT and setf-THAT be created. The use of :accessor-prefix nil says generate methods for all the slots. So there is no bug here. Probably what you should be doing is: (defclass bar (foo) ((this :initform 'b) ; simply define a new initial value (that :initform 'c :accessor that)) ) Then you would get the behavior you want. NOTE: we decided last week to remove the :accessor-prefix and :reader-prefix options from defclass. This means that you will have to start using just :accessor and :reader. Sorry for the delay in answering this message.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 12:58:20 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 09:45:11 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 09:45:38 PDT Date: 29 Sep 87 09:45 PDT From: Gregor.pa@Xerox.COM Subject: Re: Issues on Dynamic Extent for CALL-NEXT-METHOD In-reply-to: Dick Gabriel 's message of 21 Sep 87 21:35 PDT To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870929-094538-1995@Xerox> Today I talked to Guy Steele on the phone, and I told him about generic functions, methods, and call-next-method without expressing any opinions about them. When I asked what extent call-next-method should have, he thought for a while and stated `dynamic.' When I asked why, he gave argument 4, which talks about the capture of hidden state. I guess I don't think this has any weight because I have no way of knowing exactly how you described this to him. Many of your messages suggest that you think of a generic function as a 'black box' with hidden state, its likely you conveyed that feeling while you were describing it. I believe this is a bad way to think of them, I don't see any hidden state in a generic function at all. In particular, we worked very hard while we were doing declarative method combination to make sure that there was no hidden state; that the entire behavior of the method combination was exposed and clear. I really think it would be unfortunate to make this dynamic extent. It will just be yet another piece of inconvenience and complication we inflict on people trying to understand Common Lisp. Whats more, once people really get to understand generic functions and method combinations they will scratch their heads and wonder why the hell we did it.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 12:39:29 EDT Date: 29 Sep 87 0928 PDT From: Dick Gabriel Subject: Various Decisions To: Common-lisp-object-system@SAIL.STANFORD.EDU On the implicit block proposal, I agree with Moon's writeup. On NEXT-METHODS, I prefer NEXT-METHOD to avoid the potential confusion that RPLACD might cause for users. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 29 Sep 87 12:13:59 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 29 Sep 87 08:59:27 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 29 SEP 87 08:59:34 PDT Date: 29 Sep 87 08:59 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Amendments requiring additional writing In-reply-to: David A. Moon 's message of Mon, 28 Sep 87 18:43 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870929-085934-1876@Xerox> I haven't been able to figure out what you mean here. Editing out the parts of your comment I don't understand leaves "Redefining the class should set the value of the class slots", which we've never said before and I don't think I agree with. Here are two cases to think about: (1) A class slot whose value is a list of all the instances, initialized to nil when the class is first defined and updated by an initialize-instance method. (2) A class slot whose value is the price of an instance, initialized by :initform in the defclass. In case 1, you surely don't want the slot value reset to nil when you redefine the class. In case 2, you might want to set the price to the new value of the :initform. If redefining a class always reinitializes class slots, you can't do case 1. If it never reinitializes class slots, you can work around case 2 by doing setf of slot-value at the same time as you redefine the class. These are interesting examples, and cause one to ponder. I think the difference here is like the difference between editing a function definition on a file and editing the actual function list structure with a structure editor. Changing a function using a structure editor affects existing calls, and editing the file cannot. I think the corresponding cases for classes are: use the metaobject protocol to update an existing class using the slot objects that currently exist, and reevaluating the defclass form. In the latter case, the specification only guarantees that class objectsame object identity is preserved, unless we want to go more into a DWIM mode, that is guess which items in the new definition are meant to yield the same result as the old case. If in the new version of the class there is a shared slot of the same name as any local slot in the old version of the class, that shared slot is initialized to the value of the corresponding {\bf :initform} option of the new class, or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. Shared slots are not affected by the updating of an instance. This again seems mistaken for me. What value should go in the new shared slot -- that is, from which particular instance will it be set. You didn't read what I said, which is that the new shared slot is initialized from the initform, not from any particular instance. That indicates that what I wrote wasn't written clearly enough. You are right. I didn't read well enough. Your text is correct. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 22:35:43 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 19:18:18 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243701; Mon 28-Sep-87 22:18:15 EDT Date: Mon, 28 Sep 87 22:18 EDT From: David A. Moon Subject: Re: Redefining Classes To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870928-145131-19538@Xerox> Message-ID: <870928221802.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Summary: When redefining a class causes instances to be updated can be implementation-dependent. (update-from-obsolete-instance instance added-slot-names removed-slot-names removed-bound-slot-values); the primary method uses initforms to initialize the slots whose names are listed in added-slot-names. update-from-obsolete-instance is called no later than the first slot read or write after the class is redefined. The retained slot values are already in place when update-from-obsolete-instance is called. Those are my opinions. Date: 28 Sep 87 14:51 PDT From: Danny Bobrow If the redefinition of a class causes the structure of its instances to be different... I think we're going to have to define this more precisely. I see two options: (1) Adding or removing an instance slot definitely changes the structure, and some other operations may also change the structure, depending on the implementation. (2) The structure changes if and only if the value of (class-all-instance-slot-names class) is not EQUAL to its previous value. I made up the function name class-all-instance-slot-names, but you get the idea. Note how class-all-slot-names won't work. The big difference between option 1 and option 2 is that with option 2, a given sequence of defclass forms will produce exactly the same sequence of calls to make-instances-obsolete in all implementations. I'm inclined to option 2, because it is more precise, but I'm worried that this might rule out some implementation possibility. Also, for this to be meaningful and portable, we have to define the exact order of slots produced by slot inheritance, which is not something we've had to specify before now. I agree with you on the choice of how one specifies this. In the metaobject protocol, we currently have a generic function all-slot-names class &optional allocation which returns a list of slot names. The allocation argument can be an allocation symbol (e.g. :instance, :class), or nil meaning names for slots regardless of allocation. For allocation = :instance, the list returned by the implementation should be one that is ordered by the implementation. Thee is no method to specify the order of instance slots in the instance. An implementation is free to decide on the layout (e.g. so that reversing two slot names in a defclass form does not necessarily obsolete the instances). By documenting all-slot-names, we can avoid the specification of the ordering rules, and still provide a specification of what we mean. So what you're saying is that alternatives 1 and 2 are really the same. We can say that defclass calls make-instances-obsolete precisely when the value of (class-all-slot-names class ':instance) is not EQUAL to its former value, but then we can obscure that by not specifying precisely what class-all-slot-names does. OK, let's not try to define precisely when defclass calls make-instances-obsolete. I have two problems with [update-obsolete-instance]. The easy problem is that I don't like the name update-obsolete-instance, because the instance doesn't really seem obsolete to me. One idea is to take an analogy to class-changed and call it class-redefined. In Flavors we call it transform-instance, but it doesn't have quite the same semantics. It's likely that someone can think of a better name than any of these. We could call it update-from-obsolete-instance, or conform-instance-to-class. Since it takes ans instance as an argument, I don't like names like class-redefined -- which seems to focus on the class. Good point. update-from-obsolete-instance appeals to me, although it might be thought to imply that two instances are involved. Much more important, I can't implement the specification that the slots are initially uninitialized and then they are filled in from values saved in a property list. There are two problems, one obvious and one subtle. The obvious problem involves slots that were unbound originally; since there is no Lisp value that means "unbound", there is nothing that can be put into the property list for these slots. But if we don't put any entry in the property list, then the desired feature that the method can tell which slots were added or removed is lost; these slots look like they were added, even though they weren't. We could designate such a value (make it be the value of a globally accessible variable). Then putting such a value in a slot would be equivalent to making it unbound. I can hear the ARGHHH from here, but it does make accessible something that we are having to make programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste (and I could be convinced on this fairly easily), why is it you could not implement this -- is there a particular tradeoff that you are not being explicit about? It doesn't work to have a magic Lisp object that means "unbound" when it's the value of a slot, because then you can never talk about that value in any way that involves putting it into a slot. If you think that's a matter of taste, the other answer is that my hardware has the unbound slot value built into it, and it would cost me a couple million dollars to change it. Here we have both the rarified philosophical argument and the businesslike pragmatic argument. Also, the default method you mention below will put the :initform value into these previously unbound slots, which seems wrong. "Unbound" should not be confounded with "nonexistent." I feel that making unbound slots be initialized is a feature, not a bug. One good reason to make a class obsolete may be to cause formerly unbound slots to be initialized. That is, one could redefine a class, adding an initform option, and be sure that any instances that had that slot unbound would now have it bound to the specified value. To my way of thinking it is philosophically inconsistent to have different rules for whether a slot's value is changed when the class is redefined, depending on slot-boundp. At this level, "unbound" should be treated like just another value. I hope you don't think this is too inconsistent with what I said just above: "unbound" is a slot value, but it is not a Lisp object. I think it's better to do things like filling in previously unbound slots in old instances with update-from-obsolete-instance (or whatever name we choose) methods. The subtle problem involves some language extensions that we have, allowing slots to have contents that cannot be expressed as Lisp values in a property list. For instance, there is a mechanism similar to Prolog logic-variables which allows two slots to be linked together. This linkage has to be preserved in the face of class redefinition. Can such linked values only be used inside of objects, and not within lists? I though inivisible pointers can be used anywhere. I don't understand what the assumptions underlying this extension are. They can be used in lists, but the point is that care needs to be exercised when moving them around. The net effect is that the code that moves slot values from one piece of memory to another, when an instance has to have new memory allocated for it, can't be written portably in our system. But I don't see why anyone would want a portable version of it. For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Without the reasons given above, I still like this proposal as well as the one I wrote up. It supports the proposed model at a better level. I suggest conveying the desired information directly, rather than trying to be clever: Give update-obsolete-instance four arguments: the instance a list of the names of all added slots a list of the names of all deleted slots a property list giving the values of all deleted, bound slots I actually think this is fine. But I would also say that the underlying implemention also initializes existing slots that were unbound, using the initforms in the class, if any. I still think that is philosophically inconsistent. I would say the default method initializes only the newly added slots. Fine I will write it up this way. Thanks. Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. We're going to have to specify this a little more precisely, I suspect. We should specify when is the latest time that an implementation can call update-obsolete-instance, and then say that it is permitted to call it any time earlier (after the class has been redefined). I now believe that the latest time can simply be the time any of the four slot access and modification functions (or internal equivalent) is called, in spite of all the flaming against this we engaged in while discussing Danny's proposal at the meeting last week. Agreed. I'd like to hear Patrick's opinion on this timing issue before I have much confidence that we have figured it out.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 21:50:15 EDT Date: 28 Sep 87 1836 PDT From: Dick Gabriel Subject: Shared/local;class/instance To: common-lisp-object-system@SAIL.STANFORD.EDU Danny writes: ``I can't imagine them knowing anything else after they read the documentation once.'' Names can cloud an explanation: If I named the FFT function DELETE-ALL-FILES, one might allow the possibility of a user believing something else after reading the documentation (even after reading it a hundred times). Here :class is not such an offender, but the only reliable impression from the name and explanation is that the slot is in the class object - perhaps the class uses it for private information and the instances cannot see it: that information would be conveyed by :shared. Danny again: ``I answered your last question earlier -- referring to the use of dynamic as an implementation tradeoff that is not relevant for shared slots.'' But the irrelevancy is not necessary. Danny adds: I don't think we need yet another programming language.... I would rather use the symbol that specifies the option as our means of referring to the type of slot, rather than another word that refers to a property of that kind of slot.'' I suppose it's open for debate whether its type is a property of a thing, but I agree that another programming language is bad idea. Therefore, I simply believe that :shared is a better name than :class in terms of being intuitive. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 21:21:04 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 18:04:27 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243671; Mon 28-Sep-87 21:04:59 EDT Date: Mon, 28 Sep 87 21:05 EDT From: David A. Moon Subject: Re: fixing our problems with setf To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <22711.559872952@hplabsz> Message-ID: <870928210505.2.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Mon, 28 Sep 87 18:15:52 MST From: kempf%hplabsz@hplabs.HP.COM > Add to Common Lisp the same concept of "setf functions" that we are > already introducing in CLOS. Right now, Common Lisp only has "setf I endorse this. I don't see any need to change the TRACE proposal, since (SETF ) was one of the function specifications included. Do you? No, the TRACE proposal should fit right in. When I said TRACE needed to be changed, I was referring to the current state of Common Lisp, before implementation of any proposals.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 21:14:43 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 18:00:36 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243663; Mon 28-Sep-87 21:01:23 EDT Date: Mon, 28 Sep 87 21:01 EDT From: David A. Moon Subject: Re: Various Topics Discussed Last Week To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870928-164145-1052@Xerox> Message-ID: <870928210120.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 28 Sep 87 16:41 PDT From: Danny Bobrow JAK This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful It is easy for a :BEFORE method to get around this by simply side-effecting the initarg list I don't think we have said that this is either possible or legal. In fact since the initarg list is received by the :BEFORE method for INITIALIZE-INSTANCE as an &rest arg list (if received at all; the method might have only &key parameters and no &rest parameter), I believe it would be a violation of Common Lisp to modify it. Once upon a time we allowed side-effecting the initarg list in Flavors, so I have reasons to be opposed to allowing it in CLOS. Programmers using method combination always have to take into account the contract of methods they are combined with, or possibly lose. I agree that that is true. I don't see this as any worse than: JAK Users redefine these qualified methods at their own peril, as is the case with redefining any system defined method (or function for that matter). I guess the upshot is that I am not uphappy for users using :BEFORE methods, since they can achieve the results they want easily, and can know the effect of their programs. I still think that by allowing :BEFORE methods on INITIALIZE-INSTANCE we are creating an attractive nuisance. Perhaps the good effects of using standard method combination instead of introducing something special outweigh the bad effects of occasionally trapping a user into trying to write code that won't work, but it's something to think about.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 20:48:33 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 17:34:02 PDT Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 17:14:58 pdt Return-Path: Received: from hplabsz by hplabsz; Mon, 28 Sep 87 18:15:55 pdt To: "David A. Moon" Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: fixing our problems with setf X-Mailer: mh6.5 In-Reply-To: Your message of Mon, 28 Sep 87 16:55:00 -0400. <870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Mon, 28 Sep 87 18:15:52 MST Message-Id: <22711.559872952@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > Add to Common Lisp the same concept of "setf functions" that we are > already introducing in CLOS. Right now, Common Lisp only has "setf I endorse this. I don't see any need to change the TRACE proposal, since (SETF ) was one of the function specifications included. Do you? jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 20:06:49 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:51:36 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 16:51:05 PDT Date: 28 Sep 87 16:51 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Various Topics Discussed Last Week In-reply-to: David A. Moon 's message of Mon, 28 Sep 87 13:07 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870928-165105-1096@Xerox> JAK: Someone could write a forwarding metaobject method as: (defmethod no-applicable-method ((gf forwarding-generic-function) &rest all-arguments) (apply #'forward-method all-arguments)) A user can do something similar with the default method, with somewhat hairier code. Moon:The problem with this is that people want forwarding for "all" generic functions, not just specially identified ones. I put "all" in quotation marks because after they have thought about it deeply they usually discover that there are some generic functions that mustn't forward. However, I like your suggestion anyway. If we make the arguments to no-applicable-method be generic-function &rest all-arguments, someone who wants to do delegation can redefine the default method to call a new generic function with whatever arguments they want. Not having that built into CLOS doesn't make it impossible to add on one's own. Much as I dislike having to give up this feature, I have to admit that what is being given up is one generic function call after redefining the default method. Given the groans I heard when I apecialized on the first argument, I will write this up as suggested, with only two arguments to no-applicable-method, generic-function and function-arguments. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 20:02:25 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:48:27 PDT Received: from Salvador.ms by ArpaGateway.ms ; 28 SEP 87 16:41:45 PDT Date: 28 Sep 87 16:41 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Various Topics Discussed Last Week To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870928-164145-1052@Xerox> [Should the name of this option be :DEFAULT-INITARGS or :DEFAULT-INITARG ?] :DEFAULT-INITARGS to emphasize that it is a list, each of which itself is a DEFAULT-INITARG. JAK Something needs to be said here about the case where a user writes a :BEFORE method and SETF's the slot there. From the rest of the text, it sounds as if INITIALIZE-INSTANCE is permitted to clobber that slot. Moon: I think that's what we agreed to at the meeting a couple weeks ago. JAK This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful for slot initialization. The result requires either that INITIALIZE-INSTANCE be singled out in a particular way to prohibit :BEFORE methods, or allows the system to arbitrarily clobber something the programmer has done. Moon: I agree with you. First, the clobbering is not arbitrary, but a well defined part of the interface. Second, It is easy for a :BEFORE method to get around this by simply side-effecting the initarg list, as well as by doing its setf. Programmers using method combination always have to take into account the contract of methods they are combined with, or possibly lose. I don't see this as any worse than: JAK Users redefine these qualified methods at their own peril, as is the case with redefining any system defined method (or function for that matter). I guess the upshot is that I am not uphappy for users using :BEFORE methods, since they can achieve the results they want easily, and can know the effect of their programs.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 19:27:49 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 16:11:49 PDT Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 16:10:56 pdt Return-Path: Received: from hplabsz by hplabsz; Mon, 28 Sep 87 17:11:52 pdt To: "David A. Moon" Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: Various Topics Discussed Last Week X-Mailer: mh6.5 In-Reply-To: Your message of Mon, 28 Sep 87 13:07:00 -0400. <870928130706.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Mon, 28 Sep 87 17:11:49 MST Message-Id: <21934.559869109@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > One way out of this dilemma is to simply have the :BEFORE method and the > :AROUND method for INITIALIZE-INSTANCE be reserved for the system. > Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE. > This would leave no places where user defined hooks could be inserted before the > INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods > at their own peril, as is the case with redefining any system defined > method (or function for that matter). > I don't see how the methods could be reserved, since there isn't just one; > there's one for every class. However, your proposal is essntially the same > as my proposal to have a specialized kind of method combination for these > generic functions, so that user-defined methods would naturally go only where > they made sense. For some reason that proposal provoked a lot of opposition, > so I dropped it. It could be revived if there is renewed interest. In the > meantime, I won't try to put anything about this into the draft object > creation proposal. They are reserved in the same way that the symbol INITIALIZE-INSTANCE is reserved for a particular generic function which has system defined methods that you redefine at your own risk. I think what I meant is that the qualified methods are defined by the system for use in implementation dependent ways, in the same way a default INITIALIZE-INSTANCE method is provided. I don't think that INITIALIZE-INSTANCE needs to be signalled out with a special kind of method combination. However, if there's strong opposition to this, then maybe an addition to the paragraph in the initialization concepts section which begins "Note: nothing is guaranteed about ...." along the lines of "Users are encouraged to redefine the INITIALIZE-INSTANCE primary if they want to modify slot initialization, rather than using a :BEFORE qualifed method, since the default INITIALIZE-INSTANCE method will always modify the slots if required by the -initarg-list-, regardless of the initial state of the slots." This would at least warn users that :BEFORE method combination won't work as they may think in this case. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 19:09:34 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:56:13 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243560; Mon 28-Sep-87 18:57:01 EDT Date: Mon, 28 Sep 87 18:57 EDT From: David A. Moon Subject: Re: fixing our problems with setf To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870928-141913-19460@Xerox> Message-ID: <870928185703.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 28 Sep 87 14:18 PDT From: Danny Bobrow As with regular functions, associated with any given name you can have a setf function or a setf macro, but not both. This means that one does not define a setf function (with defmethod or defgeneric) and also call defsetf. The mere act of defining the setf function is enough to tell setf what to do. Does this mean that if I do a (defsetf foo ...) (defun (setf foo) ...) then the setf macro has been undone. (I hope so). And similarly in the other direction. That's the idea. I didn't give a reference to CLtL because, earlier, I wasn't able to find anything that says what (defmacro foo ...) (defun foo ...) does (nor what the other direction does). I guess this is supposed to be covered by the second to last sentence on p.67 and the second to last sentence on p.144, although neither is as clear as I would like. I changed my file copy of this message to say Note that defining a setf function after doing a defsetf or a define-setf-method removes the setf macro, and conversely defining a setf macro undefines the setf function.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 19:04:48 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:49:01 PDT Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 15:48:45 pdt Return-Path: Received: from hplabsz by hplabsz; Mon, 28 Sep 87 16:49:43 pdt To: Patrick H Dussud Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: draft of built-in method combination types X-Mailer: mh6.5 In-Reply-To: Your message of Mon, 28 Sep 87 11:14:24 -0500. <2768832864-16341119@Jenner> Date: Mon, 28 Sep 87 16:49:41 MST Message-Id: <21568.559867781@hplabsz> From: kempf%hplabsz@hplabs.HP.COM > > > A primary method has the name of the method combination type as its > sole qualifier. For example, the method combination type AND > recognizes methods whose sole qualifier is AND; these are primary > methods. > I thougt about it some more and found two disadvantages in qualifying > primary methods: > When one wants to change the method-combination type (from NCONC to > APPEND), one has to change the qualifiers of all the primary methods in > the source files. > Automatic method generators will have to know about the method > combination type. > Another disadvantage is forbidding CALL-NEXT-METHOD within primaries, which was in my earlier message. This introduces an additional level of conceptual complexity which destroys the clean semantics of CALL-NEXT-METHOD. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 19:04:00 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 15:46:18 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243539; Mon 28-Sep-87 18:43:00 EDT Date: Mon, 28 Sep 87 18:43 EDT From: David A. Moon Subject: Re: Amendments requiring additional writing To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870928-133654-19356@Xerox> Message-ID: <870928184306.6.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 28 Sep 87 13:34 PDT From: Danny Bobrow A slightly modified version of Moon's pararaph to remove references to change-class 1-11: Replace the last paragraph with the following two paragraphs: If in the new version of the class there is an instance slot of the same name as any slot in the old version of the class, the value of that slot will be the same in both instances. This means that if the slot has a value, the value returned by {\bf slot-value} after the class is redefined {\bf eql} to the value returned by {\bf slot-value} before the class is redefined. Similarly, if the slot was uninitialized, it remains uninitialized. You're right, I spazzed in editing and shouldn't have copied those references to change-class from the old text. Oh, wait, it wasn't an editing spazz, I said a bit later in the message that I was just finishing up the amendments from last March and not trying also to do all the rewriting of the document to suit our latest mind changing. However I agree with the new wording, except for the typo you introduced (missing "is"). On the issue of whether we say "class slot" or "shared slot", I do not have an opinion. It would be nice if we could work out the wording of this part of the document without doing a lot of switching back and forth on that terminology, though; we could fix the terminology afterwards. This is fine so far. But the following is problematic. At the moment a class is redefined, if the new version of the class contains a shared slot of the same name as any shared slot in the old version of the class, the value of that slot will be the same in both. Should this be true? Will changing the context of the defclass form not effect the value of the class slot. I think this is a mistake. Redefining the class should set the value of the class slots, and whether that value is EQL or not must depend on the evaluation form and context. I haven't been able to figure out what you mean here. Editing out the parts of your comment I don't understand leaves "Redefining the class should set the value of the class slots", which we've never said before and I don't think I agree with. Here are two cases to think about: (1) A class slot whose value is a list of all the instances, initialized to nil when the class is first defined and updated by an initialize-instance method. (2) A class slot whose value is the price of an instance, initialized by :initform in the defclass. In case 1, you surely don't want the slot value reset to nil when you redefine the class. In case 2, you might want to set the price to the new value of the :initform. If redefining a class always reinitializes class slots, you can't do case 1. If it never reinitializes class slots, you can work around case 2 by doing setf of slot-value at the same time as you redefine the class. I also have a problem with: If in the new version of the class there is a shared slot of the same name as any local slot in the old version of the class, that shared slot is initialized to the value of the corresponding {\bf :initform} option of the new class, or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. Shared slots are not affected by the updating of an instance. This again seems mistaken for me. What value should go in the new shared slot -- that is, from which particular instance will it be set. You didn't read what I said, which is that the new shared slot is initialized from the initform, not from any particular instance. That indicates that what I wrote wasn't written clearly enough. I think the correct paragraph would read: If in the new version of the class there is a class slot of the same name as any instance slot in the old version of the class, that class slot is initialized by the redefinition of the class, and is not affeced by the value of any slot in any of the instances. The last two lines are the addition here, and it seems like a good idea to bring this out very explicitly. I don't know that it was necessary to remove the definition of what it means for a slot to be initialized by the redefinition of the class. If there is an instance slot in the new definition of the class that is the same name as a class slot in the old version of the class, then on updating, the value of each instance slot is given the same (EQL) value as the that in the old class slot. If the class slot in the old version of the class was uninitialized, then the instance slots in the new instances are initialized as if they were new slots in the instance. This was already covered by the first paragraph, which evidently needs to be made more explicit that when it says "the same name as any slot" it means any slot, including both class and instance slots. However, I don't agree with your last sentence. I think it's much simpler to say that uninitialized slots remain uninitialized, regardless of the allocation, rather than to make a special case for slots that are both uninitialized and switching from class allocation to instance allocation. Maybe a more succinct way to say this is that if you really want to reinitialize a slot, you should remove it and then add it back. Actually, though, now that we got rid of the sequential class redefinition idea, that doesn't work unless you contrive to update every instance before redefining the class the second time. I shouldn't be surprised that one has to give up a few things when adopting the simpler scheme. Looks like we need a couple more iterations on the writing of this couple of paragraphs.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 18:06:55 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:51:03 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 14:51:31 PDT Date: 28 Sep 87 14:51 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Redefining Classes In-reply-to: David A. Moon 's message of Thu, 24 Sep 87 23:35 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870928-145131-19538@Xerox> If the redefinition of a class causes the structure of its instances to be different... I think we're going to have to define this more precisely. I see two options: (1) Adding or removing an instance slot definitely changes the structure, and some other operations may also change the structure, depending on the implementation. (2) The structure changes if and only if the value of (class-all-instance-slot-names class) is not EQUAL to its previous value. I made up the function name class-all-instance-slot-names, but you get the idea. Note how class-all-slot-names won't work. The big difference between option 1 and option 2 is that with option 2, a given sequence of defclass forms will produce exactly the same sequence of calls to make-instances-obsolete in all implementations. I'm inclined to option 2, because it is more precise, but I'm worried that this might rule out some implementation possibility. Also, for this to be meaningful and portable, we have to define the exact order of slots produced by slot inheritance, which is not something we've had to specify before now. I agree with you on the choice of how one specifies this. In the metaobject protocol, we currently have a generic function all-slot-names class &optional allocation which returns a list of slot names. The allocation argument can be an allocation symbol (e.g. :instance, :class), or nil meaning names for slots regardless of allocation. For allocation = :instance, the list returned by the implementation should be one that is ordered by the implementation. Thee is no method to specify the order of instance slots in the instance. An implementation is free to decide on the layout (e.g. so that reversing two slot names in a defclass form does not necessarily obsolete the instances). By documenting all-slot-names, we can avoid the specification of the ordering rules, and still provide a specification of what we mean. I have two problems with [update-obsolete-instance]. The easy problem is that I don't like the name update-obsolete-instance, because the instance doesn't really seem obsolete to me. One idea is to take an analogy to class-changed and call it class-redefined. In Flavors we call it transform-instance, but it doesn't have quite the same semantics. It's likely that someone can think of a better name than any of these. We could call it update-from-obsolete-instance, or conform-instance-to-class. Since it takes ans instance as an argument, I don't like names like class-redefined -- which seems to focus on the class. Much more important, I can't implement the specification that the slots are initially uninitialized and then they are filled in from values saved in a property list. There are two problems, one obvious and one subtle. The obvious problem involves slots that were unbound originally; since there is no Lisp value that means "unbound", there is nothing that can be put into the property list for these slots. But if we don't put any entry in the property list, then the desired feature that the method can tell which slots were added or removed is lost; these slots look like they were added, even though they weren't. We could designate such a value (make it be the value of a globally accessible variable). Then putting such a value in a slot would be equivalent to making it unbound. I can hear the ARGHHH from here, but it does make accessible something that we are having to make programmable (e.g. SLOT-MAKUNBOUND ...). Aside from matters of taste (and I could be convinced on this fairly easily), why is it you could not implement this -- is there a particular tradeoff that you are not being explicit about? Also, the default method you mention below will put the :initform value into these previously unbound slots, which seems wrong. "Unbound" should not be confounded with "nonexistent." I feel that making unbound slots be initialized is a feature, not a bug. One good reason to make a class obsolete may be to cause formerly unbound slots to be initialized. That is, one could redefine a class, adding an initform option, and be sure that any instances that had that slot unbound would now have it bound to the specified value. The subtle problem involves some language extensions that we have, allowing slots to have contents that cannot be expressed as Lisp values in a property list. For instance, there is a mechanism similar to Prolog logic-variables which allows two slots to be linked together. This linkage has to be preserved in the face of class redefinition. Can such linked values only be used inside of objects, and not within lists? I though inivisible pointers can be used anywhere. I don't understand what the assumptions underlying this extension are. For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Without the reasons given above, I still like this proposal as well as the one I wrote up. It supports the proposed model at a better level. I suggest conveying the desired information directly, rather than trying to be clever: Give update-obsolete-instance four arguments: the instance a list of the names of all added slots a list of the names of all deleted slots a property list giving the values of all deleted, bound slots I actually think this is fine. But I would also say that the underlying implemention also initializes existing slots that were unbound, using the initforms in the class, if any. I would say the default method initializes only the newly added slots. Fine I will write it up this way. Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. We're going to have to specify this a little more precisely, I suspect. We should specify when is the latest time that an implementation can call update-obsolete-instance, and then say that it is permitted to call it any time earlier (after the class has been redefined). I now believe that the latest time can simply be the time any of the four slot access and modification functions (or internal equivalent) is called, in spite of all the flaming against this we engaged in while discussing Danny's proposal at the meeting last week. Agreed.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 17:36:41 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:18:36 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 14:19:13 PDT Date: 28 Sep 87 14:18 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: fixing our problems with setf In-reply-to: David A. Moon 's message of Mon, 28 Sep 87 16:55 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870928-141913-19460@Xerox> As with regular functions, associated with any given name you can have a setf function or a setf macro, but not both. This means that one does not define a setf function (with defmethod or defgeneric) and also call defsetf. The mere act of defining the setf function is enough to tell setf what to do. Does this mean that if I do a (defsetf foo ...) (defun (setf foo) ...) then the setf macro has been undone. (I hope so). And similarly in the other direction. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 17:25:54 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 14:06:58 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243408; Mon 28-Sep-87 17:05:34 EDT Date: Mon, 28 Sep 87 17:05 EDT From: David A. Moon Subject: Various Topics Discussed Last Week To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <16906.559842149@hplabsz> Message-ID: <870928170524.0.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Mon, 28 Sep 87 09:42:29 MST From: kempf%hplabsz@hplabs.HP.COM 2) On blocks in methods: I agree that Alternative 1 would be best. Users who want something different can either use a :AROUND method, as Moon suggested, or program their own generic function dispatching function, using the metaobject protocol. Since we all seem to be agreed on this, I added the following to my clos-decisions file, which can be used as a resource to make sure we don't forget to document this decision: 2-34 Add to Remarks field: The body of (DEFMETHOD -name- ...) is surrounded by an implicit block named -name-, if that is a symbol, or -name1-, if -name- is (SETF -name1-), by analogy with DEFUN. The same applies to methods defined by the :METHOD option to DEFGENERIC, GENERIC-FLET, GENERIC-LABELS, and WITH-ADDED-METHODS. There is no implicit block around the body of a method defined by the :METHOD option to GENERIC-FUNCTION. Dissenters speak now. 7) On NEXT-METHODS: The primary reason is for being able to tell if calling CALL-NEXT-METHOD would signal an error. I understand Masinter's concern, and wonder if perhaps it might not be better to handle this with Ken Pitman's error proposal. Other than finding out whether a call to CALL-NEXT-METHOD is valid, there isn't much use for the list of next methods, as Masinter has pointed out. I have no real opinion on this, but we could change this to NEXT-METHOD, which returns the method object that CALL-NEXT-METHOD would call if there is one, and returns NIL if CALL-NEXT-METHOD would signal the no-more-methods error. Then we wouldn't have to worry about the implications of consing, rplac'ing, and looking at the list.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 17:10:58 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 13:54:51 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243389; Mon 28-Sep-87 16:55:16 EDT Date: Mon, 28 Sep 87 16:55 EDT From: David A. Moon Subject: fixing our problems with setf To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870920-190342-9834@Xerox>, <870921-091049-10309@Xerox>, <870921163510.2.MOON@EUPHRATES.SCRC.Symbolics.COM>, <2768308570-8410382@Jenner>, <16906.559842149@hplabsz> Message-ID: <870928165521.9.MOON@EUPHRATES.SCRC.Symbolics.COM> The goal is to unify the handling of "setf functions" with the handling of regular functions, so we don't need a proliferation of -setf versions of defmethod, defgeneric, ensure-generic-function, fboundp, generic-labels, with-added-methods, etc. The major issue is that Common Lisp has not seen a need to do this already, so the onus falls on CLOS. In addition, we ran into difficulty with confusion between the idea of associating a function name with a function object (in our case, a generic function object), and the idea of associating a way to setf a function with that function. This proposal unifies those ideas. I believe the following proposal neatly solves the problem. Add to Common Lisp the same concept of "setf functions" that we are already introducing in CLOS. Right now, Common Lisp only has "setf macros", which are defined by define-setf-method and both forms of defsetf. I draw the distinction because a "setf macro" is something that produces code (or other specifications, as in define-setf-method) which, when evaluated, will perform the effect of an invocation of setf, while a "setf function" is something that is called to perform directly the effect of an invocation of setf. As with regular functions, associated with any given name you can have a setf function or a setf macro, but not both. This means that one does not define a setf function (with defmethod or defgeneric) and also call defsetf. The mere act of defining the setf function is enough to tell setf what to do. Since setf functions are in a separate, but parallel, namespace from regular functions, we need a way to name them. The simplest way is to allow a list (setf -name-) to be used as the name of the setf function that is called to perform the effect of (setf (-name- ...) ...). The following functions, macros, and special forms defined in CLtL need to be enhanced to accept such lists where they now accept symbols as function names: compile defun disassemble documentation fboundp flet fmakunbound function labels symbol-function and setf of symbol-function trace untrace The following functions, macros, and special forms defined in CLOS need to be enhanced in the same way: defgeneric defmethod ensure-generic-function generic-flet generic-labels with-added-methods defmethod-setf and defgeneric-setf need to be removed. Note that in Common Lisp, setf macroexpansion is an operation on function names, not on functions. It differs from some dialects of Scheme, such as T, in this respect. This proposal does not attempt to change that. Note that I do not propose to introduce lexically local setf macros, that is, a cross between defsetf and macrolet. This does not appear to be logically necessary. If someone else wants this, it would certainly not be hard to do. The main issue is whether all three ways of defining lexically global setf macros need local counterparts. I also do not now propose to codify the definition of global setf macros, for example to say that (macro-function '(setf foo)) returns an expander function that takes two arguments and returns five values. The next issue is what to do about the lambda-list of a setf-function. We already agreed on what is the lambda-list in the expansion of (defun (setf foo) ...) into (setf (symbol-function '(setf foo)) #'(lambda ...)). Specifically, #'(setf foo) takes one more required argument than #'foo, and the last required argument is the new value to be stored. The issue is whether certain function-defining macros should have a special syntax with two lambda-lists when defining a setf function, or should use their normal syntax. The macros in question are defun, flet, labels, defgeneric, defmethod, and the :method option to defgeneric, generic-flet, generic-labels, and with-added-methods. In favor of two lambda-lists is that it's easier for the programmer to see which parameter is bound to the new value to be stored. In favor of one lambda-list is syntactic consistency between setf functions and regular functions. At the meeting two weeks ago, we favored two lambda-lists, but I now believe that that was a mistake. The rule that the new value is the last required argument should not be at all difficult for programmers to understand. Syntactic consistency is important. The remaining issue is a scoping issue. We have introduced lexically local setf functions, where before Common Lisp only had lexically global setf macros. Thus the namespace of setf operators has been extended to have a lexical component, just like the namespace of regular operators. (Recall that "operator" means the union of functions, macros, and special forms). Regular functions and setf functions naturally come in pairs, but since they are defined separately we have to specify what happens in various cases where only one is defined at a given lexical contour. The simplest solution would be to say that (setf (-foo- ...) ...) ignores the scope of the name -foo- when considering how to setf it. However, this solution has already been ruled out by the Cleanup committee's resolution of issue GET-SETF-METHOD-ENVIRONMENT. Specifically inside the scope of a macrolet of foo, the expansion of (setf (foo ...) ...) proceeds by calling the macrolet expander, regardless of whether there is a globally defined setf macro for foo. Similarly, inside the scope of a flet of foo, (setf (foo ...) ...) is invalid. To be consistent with this, I propose a suite of three rules for the behavior of local function defining forms (flet, generic-flet, generic-labels, labels, macrolet, and with-added-methods): (1) A local function definition of the name foo implicitly shadows the scope of a global setf macro definition for foo. (2) A local function definition of the name foo implicitly shadows the scope of any enclosing function definition of (setf foo). When the same function defining form defines both foo and (setf foo), the scopes of the two names are equal regardless of their order of appearance in the function defining form. (3) A local function definition of the name (setf foo) does not change the scope of any enclosing function definition of foo. with-added-methods may require a special rule, because of its unusual half-shadowing semantics. I'm inclined to ignore this and say that (with-added-methods ((foo ...)) ...) shadows any enclosing definition of (setf foo), just like generic-labels. Example (for Patrick): (defmethod (setf subseq) ((sequence vector) start (new-value vector) &optional end) (unless end (setq end (length sequence))) (setq end (min end (+ start (length new-value)))) (do ((i start (1+ i)) (j 0 (1+ j))) ((= i end) new-value) (setf (aref sequence i) (aref new-value j)))) If this meets with general approval I will recast this for the Cleanup committee.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 16:52:55 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 13:36:18 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 13:36:54 PDT Date: 28 Sep 87 13:34 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Amendments requiring additional writing In-reply-to: David A. Moon 's message of Fri, 25 Sep 87 21:41 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870928-133654-19356@Xerox> A slightly modified version of Moon's pararaph to remove references to change-class 1-11: Replace the last paragraph with the following two paragraphs: If in the new version of the class there is an instance slot of the same name as any slot in the old version of the class, the value of that slot will be the same in both instances. This means that if the slot has a value, the value returned by {\bf slot-value} after the class is redefined {\bf eql} to the value returned by {\bf slot-value} before the class is redefined. Similarly, if the slot was uninitialized, it remains uninitialized. This is fine so far. But the following is problematic. At the moment a class is redefined, if the new version of the class contains a shared slot of the same name as any shared slot in the old version of the class, the value of that slot will be the same in both. Should this be true? Will changing the context of the defclass form not effect the value of the class slot. I think this is a mistake. Redefining the class should set the value of the class slots, and whether that value is EQL or not must depend on the evaluation form and context. I also have a problem with: If in the new version of the class there is a shared slot of the same name as any local slot in the old version of the class, that shared slot is initialized to the value of the corresponding {\bf :initform} option of the new class, or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. Shared slots are not affected by the updating of an instance. This again seems mistaken for me. What value should go in the new shared slot -- that is, from which particular instance will it be set. I think the correct paragraph would read: If in the new version of the class there is a class slot of the same name as any instance slot in the old version of the class, that class slot is initialized by the redefinition of the class, and is not affeced by the value of any slot in any of the instances. If there is an instance slot in the new definition of the class that is the same name as a class slot in the old version of the class, then on updating, the value of each instance slot is given the same (EQL) value as the that in the old class slot. If the class slot in the old version of the class was uninitialized, then the instance slots in the new instances are initialized as if they were new slots in the instance.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 16:08:57 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 12:54:12 PDT Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 12:53:34 pdt Return-Path: Received: from hplabsz by hplabsz; Mon, 28 Sep 87 13:54:30 pdt To: Patrick H Dussud Cc: common-lisp-object-system@sail.stanford.edu Subject: Re: Exact type X-Mailer: mh6.5 In-Reply-To: Your message of Tue, 22 Sep 87 11:25:11 -0500. <2768315111-8803361@Jenner> Date: Mon, 28 Sep 87 13:54:27 MST Message-Id: <19989.559857267@hplabsz> From: kempf%hplabsz@hplabs.HP.COM >x is of exact-type X if it verifies: >Let Y be a type such as (SUBTYPEP X Y) is true, >then (TYPEP x Y ) is false. Yes, except I think what you want the compiler to verify is "If for all such Y, (TYPEP x Y) is false, then x is of EXACT-TYPE X". >But allowing the other COMMON subtypes would makes programs non portable: >The list of subtypes of a type is implementation dependent. We say (page >1-14) that individual implementation can add additional subclass >relationships as long as they don't violate CLtL. But the subtype relationships in CLtL must still hold. Thus, any importabilities will be the result of importabilites in the Common Lisp type system, not in the CLOS addition. Reading the rules on pg. 33-35, it's difficult to discern importabilities, but, talking to Gregor (who has some experience in this area), they do exist. However, I think the place to address the problem is to tighten up the Common Lisp type system, not restrict EXACT-TYPE. In addition, declarations in Common Lisp have a certain flavor of implementation dependency to them anyway, as this quote from CLtL, pg. 153 should indicate: With one exception, declarations are completely optional and correct declarations do not affect the meaning of a correct program. The exception is that SPECIAL declarations _do_ affect the interpretation of variable bindings and references, and so _must_ be specified where appropriate. All other declarations are of an advisory nature, and may be used by the LISP system to aid the programmer by performing extra error checking or producing efficient compiled code. .... Note that it is considered an error for a program to violate a declaration (such as a TYPE declaration), but an implementation is not required to detect such errors (though such detection, where feasible, is to be encouraged). While I don't particularly agree with this policy, I think that it gives implementations so much latitude already that restricting EXACT-TYPE would be inappropriate. However, if anyone else feels strongly about this, or has a good counter- argument, I'd be willing to change the specification. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 15:09:40 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:54:30 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 11:55:01 PDT Date: 28 Sep 87 11:49 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Shared/local;class/instance In-reply-to: Dick Gabriel 's message of 28 Sep 87 11:17 PDT To: RPG@SAIL.STANFORD.EDU cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870928-115501-19131@Xerox> I believe we ought to pick a consistent set of names for these :allocation types and keywords. I believe that the pair shared/local makes a little more sense in that I wouldn't expect novices to know or remember that a class-allocated slot would be visible to the instances and hence shared. I can't imagine them knowing anything else after they read the documentation once. And it is more important to have only a single set of words than to have a simple property of the current pair used as an alternative. So once again I vote for instance/class rather than local/shared. I believe that things like :dynamic or :procedure, to pick up on Danny's suggestion, are of a nature orthogonal to :shared/:local, because the latter speaks of the scope of the slot rather than of any implementation technique. Continuing in this vein, it seems that many :allocation keywords ought to be allowed: why cannot a :shared slot be :dynamic as well? I answered your last question earlier -- referring to the use of dynamic as an implementation tradeoff that is not relevant for shared slots. Shall we extend the :allocation option to be either a single allocation-type or a list of them? I don't think we need yet another programming language (i.e. a method for compostion) for this option -- simple extensibility is enough. I would rather use the symbol that specifies the option as our means of referring to the type of slot, rather than another word that refers to a property of that kind of slot.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 14:36:28 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:20:42 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243109; Mon 28-Sep-87 14:19:48 EDT Date: Mon, 28 Sep 87 14:19 EDT From: David A. Moon Subject: key argument versus keyword argument To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870928-102654-18839@Xerox> Message-ID: <870928141948.3.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 28 Sep 87 10:26 PDT From: Danny Bobrow Moon asked: >Do you think it would be worth trying a version of the writeup >that uses CLtL's terminology, with a simple admonition that a >"keyword name" is not necessarily a keyword symbol? Kempf answered: Yes, this would be a good idea. I think a case can be made for a semantic distinction between keyword symbols and keyword arguments. The term keyword argument is used in Smalltalk as well, where the concept of keyword symbols does not occur. I agree with the principal -- but what about calling these "key arguments" or "&key arguments" and a "key name" is a name that identifies a key argument. That seems like a raesonable idea. At this point, as far as I am concerned I would rather follow CLtL's terminology, imperfect as it is, than spend time trying to invent new terminology. My efforts on the latter haven't been successful so far, and I'd rather work on finishing CLOS. However, if Common Lisp comes up with better terminology, we can certainly adjust the description of CLOS to match.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 14:30:58 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:13:33 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243088; Mon 28-Sep-87 14:14:24 EDT Date: Mon, 28 Sep 87 14:14 EDT From: David A. Moon Subject: Revised draft of object creation proposal To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870928141430.0.MOON@EUPHRATES.SCRC.Symbolics.COM> This version differs from the previous one I mailed out only in some small corrections based on comments received in the mail. The terminology has been changed back from "named argument" to "keyword argument." It may be about time to start converting this to the text that will go into the specification document. Any more comments first? Draft of, and notes toward, a new object creation proposal based on CLOS subcommittee discussions July 2, 1987. Updated based on Sep 17-18 1987 working group meeting. Updated based on mail received up to Sep 28, and converted back to CLtL terminology for keyword arguments. -foo- means the word foo in italics. FOO means the word foo in boldface. PREREQUISITES This proposal assumes keyword arguments to methods work as described in the accompanying lambda-list congruence proposal. The proposal assumes CL-Cleanup issue KEYWORD-ARGUMENT-NAME-PACKAGE, which stated that the names of &key arguments do not have to be keyword symbols. The terminology of CLtL is used for discussing keyword arguments, but it should be understood that keyword names are not necessarily symbols in the keyword package; that's just a default convention. CONCEPTS TO BE ADDED TO 87-002 -initarg-. An initarg (initialization argument) is a keyword argument that can be used to control object creation and initialization. The &key arguments to MAKE-INSTANCE are initargs. It is often convenient to use keyword symbols to name initargs, but the name of an initarg can be any symbol, including NIL. -initarg list-. An initarg list (initialization argument list) is a list of alternating initarg names and values. Its structure is identical to a property list and also identical to the portion of an argument list processed for &key parameters. As in those lists, if an initarg name appears more than once in an initarg list, the leftmost occurrence supplies the value and the remaining occurrences are ignored. The arguments to MAKE-INSTANCE, after the first, are an initarg list. As in an &key argument list, :ALLOW-OTHER-KEYS can appear in an initarg list, and if its value is non-NIL, error-checking of initarg names is disabled. -slot-filling initarg-. An initarg associated with a slot. If the initarg has a value in the initarg list, the value is stored into the slot of the newly-created object, overriding any initform associated with the slot. A single initarg can fill more than one slot. A slot-filling initarg that fills a shared slot stores its value into the shared slot, replacing any previous value. -method-implemented initarg-. An initarg associated with a method. When an object is created, the method is called with the initarg's value as an argument and the method uses the value in any way it likes. If the initarg has no value in the initarg list, the method's lambda-list supplies a default value. A single initarg can be implemented by more than one method. An initarg can be both slot-filling and method-implemented. CHANGES TO 87-002 FEATURES DEFCLASS gets a new :INITARG slot option, which is followed by a symbol. The symbol becomes the name of a slot-filling initarg for this class. This slot option can appear any number of times. DEFCLASS gets a new :DEFAULT-INITARGS option, which is followed by a list of alternating initarg names and default-initarg forms. If one of these initargs does not appear in the initarg list supplied to MAKE-INSTANCE, the corresponding default-initarg form is evaluated, then the initarg name and the form's value are added to the end of the initarg list. The form is evaluated every time it is used. The lexical environment in which this form is evaluated is the lexical environment in which DEFCLASS was evaluated. The dynamic environment is the dynamic environment in which MAKE-INSTANCE was called. The appearance of a symbol as an initarg name in a :DEFAULT-INITARGS option does not make that symbol a valid initarg name for the class. The :DEFAULT-INITARGS option may be specified more than once. [Should the name of this option be :DEFAULT-INITARGS or :DEFAULT-INITARG ?] Method-implemented initargs are defined simply by defining a method for INITIALIZE-INSTANCE or ALLOCATE-INSTANCE. The keyword name of each keyword parameter specifier in the method's lambda-list becomes a method-implemented initarg for all classes for which this method is applicable. Initarg inheritance: The effective set of slot-filling initargs for a class C is the union of the slot-filling initargs defined by C and its superclasses. The effective set of method-implemented initargs for a class C is determined by method inheritance. Default-initargs inheritance: The set of initargs of C that have default value forms is determined by the union of the :DEFAULT-INITARGS options of C and its superclasses. When more than one class in the CPL specifies a default value form for a given initarg, only the form specified by the most specific such class in the CPL is used. Rules when initargs are duplicated in various ways: The :INITARG slot-option may be specified more than once for a given slot. A single initarg can initialize more than one slot if the same initarg name appears in more than one :INITARG slot-option. It is valid for a given initarg name to be defined more than once as a slot-filling initarg, as a method-implemented initarg, or both. If two initargs that initialize the same slot, with the same or different names, are given in the arguments to MAKE-INSTANCE, the leftmost of these initargs in the initarg list prevails. If two different initargs that initialize the same slot have default values, and neither is given explicitly in the arguments to MAKE-INSTANCE, the initarg that appears in a :DEFAULT-INITARGS slot-option in the most specific class prevails, or if they appeared in the same class, the one whose mention in :DEFAULT-INITARGS is leftmost in the DEFCLASS form prevails. Defaulted initargs are appended to the end of the initarg list in this order. If there are two different initargs that initialize the same slot, and one was given explicitly in the arguments to MAKE-INSTANCE while the other was defaulted via :DEFAULT-INITARGS, the explicit one prevails. (This rule is implied by the two preceding rules, but it seems worth drawing attention to.) If a slot has both an :INITFORM and an :INITARG slot-option, and the slot-filling initarg is defaulted via :DEFAULT-INITARGS, the initform is not used and is not evaluated. An illustrative example of the above rules: (defclass a () ((x :initarg a))) (defclass b (a) ((x :initarg b)) (:default-initargs a 1 b 2)) FORM INITARG LIST CONTENTS OF X SLOT (make-instance 'b) (a 1 b 2) 1 (make-instance 'b 'a 3) (a 3 b 2) 3 (make-instance 'b 'b 4) (b 4 a 1) 4 (make-instance 'b 'a 1 'a 2) (a 1 a 2 b 2) 1 Note: nothing is guaranteed about the order of evaluation of default-initarg forms and initforms. If there are dependencies among these forms, you should be using INITIALIZE-INSTANCE methods instead. In most programs, the initforms and default-initarg forms are either constants or simple forms that construct new objects; forms with side-effects are permitted, but are not typically used. NEW FUNCTIONS TO BE ADDED In this section, I have only sketched each function, for the sake of brevity. Full writeups can be constructed once the overall framework has been agreed upon. Functions are in alphabetical order, in three sections at three protocol levels. The breakdown between the second and third levels may be changed. By coincidence, all functions listed except SLOT-BOUNDP and SLOT-MAKUNBOUND are generic and expected to specialize on their first argument. >>> Tools used for simple object-oriented programming: (INITIALIZE-INSTANCE instance &key &allow-other-keys) MAKE-INSTANCE calls this with the freshly-created instance, any initargs that were supplied to MAKE-INSTANCE, and any defaulted initargs. Users define methods for this to create method-implemented initargs. Typically, user-defined methods are :AFTER methods, however that is not a requirement. The primary method for INITIALIZE-INSTANCE is system-supplied and takes care of the slot-filling initargs. For each slot (whether local or shared): - if an initarg was specified or defaulted that fills that slot, its value is stored into the slot. (This is true even if a :BEFORE method has modified the slot.) - otherwise, if the slot is uninitialized and it has an initform, the initform is evaluated and the result is stored into the slot. - the duplicate-resolution rules mentioned earlier are obeyed. An implementation is permitted to optimize initforms that neither produce nor depend on side-effects, by evaluating them and storing them into slots before running any INITIALIZE-INSTANCE methods, rather than handling them in the primary INITIALIZE-INSTANCE method. This might be implemented by having the ALLOCATE-INSTANCE method copy a prototype instance. This means that :BEFORE and :AROUND methods for INITIALIZE-INSTANCE cannot rely on all the slots being uninitialized at the beginning. An implementation is permitted to optimize default value forms for slot-filling initargs by not actually consing the complete initarg list, when the only method that would see the complete list is the system-supplied primary method, e.g. when no other methods use &REST. In this case default value forms can be treated like initforms. This has no visible effects other than a performance improvement. (MAKE-INSTANCE class &key -initargs-...) => instance Users call this function to create objects. Class can be either a class or the name of a class. Meta-users can define new methods for MAKE-INSTANCE to replace the object-creation protocol. (SLOT-BOUNDP instance slot-name) => boolean Allows writing INITIALIZE-INSTANCE :AFTER methods that only initialize slots if they haven't been initialized already. (SLOT-MAKUNBOUND instance slot-name) => instance Restores a slot to the uninitialized condition. >>> Functions underlying the tools It is undefined what happens if you modify the values returned by any of the functions in this section. It is permitted, but not required, for an implementation to return values that share with internal data structures. Some of these functions will be SETF'able; which ones remain to be determined. (CLASS-ALL-INITARGS class) => list of initarg names, including inherited ones. This is (REDUCE #'UNION (MAPCAR #'CLASS-DIRECT-INITARGS cpl)). (CLASS-DIRECT-INITARGS class) => list of initarg names. This works by computing the applicable methods for ALLOCATE-INSTANCE and for INITIALIZE-INSTANCE and examining their lambda-lists (using METHOD-KEYWORD-NAMES), then combining that with the class's list of slot-filling initargs. (CLASS-ALL-INITARG-DEFAULTS class) => ((initarg-name default-value-function default-value-form)...) (CLASS-DIRECT-INITARG-DEFAULTS class) => ((initarg-name default-value-function default-value-form)...) This reflects the :DEFAULT-INITARGS option. Default-value-form is the form that was originally specified, and is retained purely for explanatory purposes. default-value-function is what gets actually called; its effect is equivalent to enclosing default-value-form in the appropriate lexical environment. Default-value-function takes no arguments. (CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...) (CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...) This reflects the :INITARG slot-option. (COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods (METHOD-KEYWORD-NAMES method) => list of symbols or &ALLOW-OTHER-KEYS, indicating the keyword names of the keyword parameter specifiers in the method's lambda-list. The result is the symbol &ALLOW-OTHER-KEYS instead of a list if the method's lambda-list contains that symbol. >>> Meta-object functions (ALLOCATE-INSTANCE class &key &allow-other-keys) => instance Meta-users can replace the system-supplied, implementation-dependent method for this. Any keyword arguments accepted by applicable ALLOCATE-INSTANCE methods become valid initargs. (CHECK-INITARGS class initarg-list) Meta-users could replace the system-supplied method that implements the normal rules for initarg validity. (DEFAULT-INITARGS class initarg-list) => initarg-list The system-supplied method implements the :DEFAULT-INITARGS class option by appending initargs that do not appear in initarg-list to the end of the returned list. The initarg-list supplied as an argument is not modified. The order of initargs appended to the list is determined by the duplicate-initarg rules listed earlier. (FINALIZE-INHERITANCE class &key slots methods initargs) This is called by the system at least once before a class is instantiated, and is called again whenever anything relevant changes. System-supplied methods for this conspire with methods for CHECK-INITARGS, etc., to make MAKE-INSTANCE faster. Users with their own optimization needs can add methods for this generic function that will precompute things based on inherited information, and update the precomputed information whenever anything changes. The :slots, :methods, and :initargs arguments are booleans that are true when the specified type of inheritance needs to be recomputed. PROCEDURAL DEFINITION OF MAKE-INSTANCE MAKE-INSTANCE behaves as if it was defined as follows, except that certain optimizations are permitted, as detailed below and in the description of INITIALIZE-INSTANCE. (defmethod make-instance ((class standard-class) &rest initargs) (setq initargs (default-initargs class initargs)) (check-initargs class initargs) (let ((instance (apply #'allocate-instance class initargs))) (apply #'initialize-instance instance initargs) instance)) (defmethod make-instance ((class-name symbol) &rest initargs) (apply #'make-instance (symbol-class class-name) initargs)) Optimization is possible, including inlining and constant-folding of method lookup and method bodies, provided that the programming environment either prohibits redefining these methods or updates everything when they are redefined. A possible example implementation would be that MAKE-INSTANCE has a separate method for every class, which is automatically written and compiled by the system. This optimization relies on the FINALIZE-INHERITANCE generic function and some unpublished slots of STANDARD-CLASS. Because of optimization, methods for the generic functions listed may not actually be called on every call to MAKE-INSTANCE, or may not receive exactly the arguments that would be expected. For example, CHECK-INITARGS may actually be called before DEFAULT-INITARGS rather than after, if it has already been determined that the default initargs will pass CHECK-INITARGS. Additional explicit details of permissible optimization will need to be set forth. MEETING OF STATED DESIGN GOALS Lexical proximity of concepts--the declaration of an initarg as valid, the specification of what it does, and the default if it is not supplied are all together, in a slot specifier or in a method lambda-list. Simple ways to do simple things--slot-filling initargs don't require the user to write any code. Method-implemented initargs work just like ordinary function arguments as far as the user is concerned. Minimal number of new languages--the only addition to Common Lisp is a mildly complicated rule for how &KEY lambda-lists of methods do validity checking. Ability to do everything at some level--the underlying procedural level is available. Functions to access all the direct and inherited information are documented. Underlying mechanism is exposed so user can use it for other things, rather than abusing instance creation as the only way to access the mechanism--the combination of &KEY, METHOD-KEYWORD-NAMES, COMPUTE-APPLICABLE-METHODS, and FINALIZE-INHERITANCE provides everything the user needs.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 14:30:15 EDT Date: 28 Sep 87 1117 PDT From: Dick Gabriel Subject: Shared/local;class/instance To: common-lisp-object-system@SAIL.STANFORD.EDU I believe we ought to pick a consistent set of names for these :allocation types and keywords. I believe that the pair shared/local makes a little more sense in that I wouldn't expect novices to know or remember that a class-allocated slot would be visible to the instances and hence shared. I believe that things like :dynamic or :procedure, to pick up on Danny's suggestion, are of a nature orthogonal to :shared/:local, because the latter speaks of the scope of the slot rather than of any implementation technique. Continuing in this vein, it seems that many :allocation keywords ought to be allowed: why cannot a :shared slot be :dynamic as well? Shall we extend the :allocation option to be either a single allocation-type or a list of them? -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 14:21:05 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 28 Sep 87 11:07:08 PDT Received: from relay2.cs.net by RELAY.CS.NET id af22832; 28 Sep 87 13:11 EDT Received: from ti-csl by RELAY.CS.NET id aj05242; 28 Sep 87 12:59 EDT Received: from Jenner by tilde id AA05968; Mon, 28 Sep 87 11:16:19 CDT Message-Id: <2768832864-16341119@Jenner> Date: Mon, 28 Sep 87 11:14:24 CDT From: Patrick H Dussud To: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Re: draft of built-in method combination types In-Reply-To: Msg of Wed, 23 Sep 87 07:27 EDT from "Sonya E. Keene" Date: Wed, 23 Sep 87 07:27 EDT From: "Sonya E. Keene" Subject: draft of built-in method combination types A primary method has the name of the method combination type as its sole qualifier. For example, the method combination type AND recognizes methods whose sole qualifier is AND; these are primary methods. I thougt about it some more and found two disadvantages in qualifying primary methods: When one wants to change the method-combination type (from NCONC to APPEND), one has to change the qualifiers of all the primary methods in the source files. Automatic method generators will have to know about the method combination type.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 14:01:36 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:47:51 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 243054; Mon 28-Sep-87 13:48:40 EDT Date: Mon, 28 Sep 87 13:48 EDT From: David A. Moon Subject: lambda-list congruence To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870928134842.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Here is the lambda-list congruence writeup, revised to use CLtL's terminology for keyword arguments instead of introducing new terminology: LAMBDA-LIST CONGRUENCE Changes to Lambda-list Congruence Rules (p.1-20): Rules 1, 2, and 6 remain the same, except for wording problems, while rules 3-5 need to be replaced to implement the new rules for &KEY and to fix the interaction among &KEY, &REST, and &ALLOW-OTHER-KEYS. The new rules for congruence are the following: These rules define the congruence of a set of lambda-lists, including the lambda-list of each method for a given generic function and the lambda-list specified with DEFGENERIC, if present. For (SETF generic) methods, these rules apply to the effective lambda-list produced by combining the two specified lambda-lists according to the rules on page nnn. 1. Each lambda-list must have the same number of required parameters. 2. Each lambda-list must have the same number of optional parameters. Each method can supply a different default for an optional parameter. 3. If any lambda-list uses &REST or &KEY, each lambda-list must use one or more of these. 4. If the DEFGENERIC uses &KEY, each method must accept all of the keyword names mentioned after &KEY in DEFGENERIC, either by accepting them explicitly, by specifying &ALLOW-OTHER-KEYS, or by specifying &REST but not &KEY. Each method can accept additional keyword arguments of its own. The checking of the validity of keyword names is not done in each method; instead it is done in the generic function. 5. The use of &ALLOW-OTHER-KEYS need not be consistent across lambda-lists. If &ALLOW-OTHER-KEYS is used in any lambda-list, then any keyword arguments may be used in the call to the generic function. 6. The use of &AUX need not be consistent across methods.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 13:40:23 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:26:25 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 28 SEP 87 10:26:54 PDT Date: 28 Sep 87 10:26 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: key argument versus keyword argument In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Mon, 28 Sep 87 09:42:29 MST To: kempf%hplabsz@hplabs.HP.COM cc: common-lisp-object-system@sail.stanford.edu Message-ID: <870928-102654-18839@Xerox> Moon asked: >Do you think it would be worth trying a version of the writeup >that uses CLtL's terminology, with a simple admonition that a >"keyword name" is not necessarily a keyword symbol? Kempf answered: Yes, this would be a good idea. I think a case can be made for a semantic distinction between keyword symbols and keyword arguments. The term keyword argument is used in Smalltalk as well, where the concept of keyword symbols does not occur. I agree with the principal -- but what about calling these "key arguments" or "&key arguments" and a "key name" is a name that identifies a key argument. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 13:21:17 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 10:06:03 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242975; Mon 28-Sep-87 13:06:58 EDT Date: Mon, 28 Sep 87 13:07 EDT From: David A. Moon Subject: Various Topics Discussed Last Week To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <16906.559842149@hplabsz> Message-ID: <870928130706.8.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: Mon, 28 Sep 87 09:42:29 MST From: kempf%hplabsz@hplabs.HP.COM Comments on excerpts from Jim's message: 1) On SETF: For purposes of finalizing the spec for the November meeting, I think we should drop reference to SETF methods. I think that would be a mistake, because it would simply be postponing the problem. I'd really like to get this stuff finished soon, and I don't think it's impossibly difficult. I will mail out a complete proposal for what to do about SETF later today. 3) On the object creation proposal: I agree with most of your comments and will update the draft proposal accordingly. >The primary method for INITIALIZE-INSTANCE is system-supplied... Something needs to be said here about the case where a user writes a :BEFORE method and SETF's the slot there. From the rest of the text, it sounds as if INITIALIZE-INSTANCE is permitted to clobber that slot. I think that's what we agreed to at the meeting a couple weeks ago. This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful for slot initialization. The result requires either that INITIALIZE-INSTANCE be singled out in a particular way to prohibit :BEFORE methods, or allows the system to arbitrarily clobber something the programmer has done. I agree with you. One way out of this dilemma is to simply have the :BEFORE method and the :AROUND method for INITIALIZE-INSTANCE be reserved for the system. Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE. This would leave no places where user defined hooks could be inserted before the INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods at their own peril, as is the case with redefining any system defined method (or function for that matter). I don't see how the methods could be reserved, since there isn't just one; there's one for every class. However, your proposal is essntially the same as my proposal to have a specialized kind of method combination for these generic functions, so that user-defined methods would naturally go only where they made sense. For some reason that proposal provoked a lot of opposition, so I dropped it. It could be revived if there is renewed interest. In the meantime, I won't try to put anything about this into the draft object creation proposal. 4) On method combination types: >An error is signaled if CALL-NEXT-METHOD is used in a primary method. In primaries as well???? If so, then we're talking about a major change, because 87-002 allows it in primaries. Or perhaps this is only for the new method combination types? Yes, this was in the context of method combination types defined by the short form of define-method-combination. If so, then I'd be interested in a reason for prohibiting method combination in primaries, since it introduces a major incompatibility between different types of method combination. If you can figure out what it would mean for a primary method in that kind of method combination to call call-next-method, please make a proposal. 10) On NO-APPLICABLE-METHOD: >( no-applicable-method generic-function first-argument &rest >all-arguments) I thought we had agreed to get rid of the first argument kludge. Otherwise, this is the only place in the entire spec where we're making a distinction between multiple dispatch object oriented programming and classical object oriented programming. The user has to go through some additional grief if all the arguments are passed as an &REST parameter in order to get forwarding, but I think that forwarding should best be left to metaobject programmers anyway, since it is, as yet, experimental (neither PCL nor New Flavors have it). Someone could write a forwarding metaobject method as: (defmethod no-applicable-method ( (gf forwarding-generic-function) &rest all-arguments ) (apply #'forward-method all-arguments) ) A user can do something similar with the default method, with somewhat hairier code. The problem with this is that people want forwarding for "all" generic functions, not just specially identified ones. I put "all" in quotation marks because after they have thought about it deeply they usually discover that there are some generic functions that mustn't forward. However, I like your suggestion anyway. If we make the arguments to no-applicable-method be generic-function &rest all-arguments, someone who wants to do delegation can redefine the default method to call a new generic function with whatever arguments they want. Not having that built into CLOS doesn't make it impossible to add on one's own.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 12:35:55 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Sep 87 09:22:25 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242911; Mon 28-Sep-87 12:23:22 EDT Date: Mon, 28 Sep 87 12:23 EDT From: David A. Moon Subject: Re: Amendments requiring additional writing To: Common-Lisp-Object-System@SAIL.STANFORD.EDU In-Reply-To: <870926-164022-17885@Xerox> Message-ID: <870928122330.4.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 26 Sep 87 16:40 PDT From: Masinter.pa@Xerox.COM While fixing typep and subtypep to deal with classes seems likely to preferable to adding instancep and subclassp, attempting to fix type-of so that it sometimes returns a class and sometimes returns a symbol seems hopeless, and bad design. type-of is so underconstrained in any case to be worthless. I think you're better off abandoning it -- e.g., implementations can return T if on instances of classes if they need to. That isn't what we decided to do when we discussed type-of earlier. The basic principal here is that class objects are legitimate type-specifiers, they are just not quite as nice to read as symbols. The fact that there is more than one type-specifier that refers to exactly the same set of objects is not new to Common Lisp. Thus making type-of return a class object when there is no meaningful symbol to return doesn't strike me as making the design of type-of any worse than it already is. I would be favorable towards a proposal to remove type-of from Common Lisp entirely, but not towards one to leave type-of in Common Lisp but declare it broken for CLOS-defined objects. Aside: this reminds me of an interesting infinite regress. Suppose the printed representation of an object is #< ... > enclosing the printed representation of the object's type-of followed by something to try to distinguish different instances of the type. Now suppose the object's type is an anonymous class, and the class's type is an anonymous metaclass, and the metaclass's type is itself. If something special isn't done, the printed representation starts with an infinite sequence of #< brackets. Of course this kind of problem is not new, and is easily solved in an ad hoc way. The proponents for disallowing careless name->value mappings will likely be unhappy with the polymorphic typep and subtypep; it might be useful to be able to lexically determine whether they might be used in a given program. That's a good point. Of course it's impossible to determine this lexically if the relevant functions are used with non-constant arguments, at least if the data flow and control structure are sufficiently complicated that the program cannot be statically fully analyzed. I see two responses to this: the radical response is, this shows how the type system in Common Lisp is misdesigned, because types are not first-class objects of their own type. Let's rip out the entire type system and replace it with a whole new one that's better designed. The conservative response is, this shows how the type system in Common Lisp is misdesigned, but let's not rip everything apart now. Instead let's figure out how to fit a better type system (CLOS) into the existing language in a smooth way. At this point I always go for the conservative approach. If I was designing a new dialect of Lisp, I wouldn't be doing it in the CL-Cleanup committee. Does anyone else see a linkage between the function-type proposal and the form for typep/instancep subtypep/subclassp type-of/class-of? Not me. Do you see a deeper linkage than the one you mentioned, that is another case of names and referents being allowed to be used interchangeably?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 11:57:32 EDT Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 28 Sep 87 08:42:03 PDT Received: from hplabsz.hpl.hp.com by hplms2; Mon, 28 Sep 87 08:41:46 pdt Return-Path: Received: from hplabsz by hplabsz; Mon, 28 Sep 87 09:42:32 pdt To: common-lisp-object-system@sail.stanford.edu Subject: Various Topics Discussed Last Week X-Mailer: mh6.5 Date: Mon, 28 Sep 87 09:42:29 MST Message-Id: <16906.559842149@hplabsz> From: kempf%hplabsz@hplabs.HP.COM After an unsuccessful search for desert bighorn sheep at 9,000 feet in the eastern Nevada mountains, here are some comments on the week's mail: 1) On SETF: I agree with Gregor that we should drop SETF methods from the language for now. I don't think requiring the user to write a DEFSETF is excessive, since SETF is currently just syntatic sugar anyway. I think I understand Patrick's concerns about not being able to use the short form, but am concerned that, if we don't drop DEFMETHOD-SETF and kin we may be wiring short term solutions into the spec which would preclude making an underlying fix, as Masinter and Gregor have suggested. I agree that we should propose a fix. I like Moon's way of defining a SETF function, and the idea of function specs in general. We seem to be continually stumbling on where they can be useful (DOCUMENTATION, TRACE, SETF functions, etc.). I think the addition of methods and generic functions to Common Lisp has magnified this lack in the underlying language. For purposes of finalizing the spec for the November meeting, I think we should drop reference to SETF methods. I'd like to co-ordinate the TRACE proposal to the cleanup committee along with anything Gregor might propose involving function specs. 2) On blocks in methods: I agree that Alternative 1 would be best. Users who want something different can either use a :AROUND method, as Moon suggested, or program their own generic function dispatching function, using the metaobject protocol. 2) On dynamic v.s. indefinite extent for CALL-NEXT-METHOD: Dynamic it is. 3) On the object creation proposal: Here are some specific comments on Moon's basenote: > The form >is evaluated in the lexical environment in which the DEFCLASS form was >evaluated. When reading this, it sounded like the form would, in addition, be evaluated when the DEFCLASS form was. From reading the rest of the basenote, I see that it is not, but some kind of forward reference here would prepare the reader. Also, from the rest of the note, it seems as if it is implementation dependent as to when the initforms are evaluated. This is fine, but should be in the concepts section as well, I think, with a warning that users need therefore to be especially concerned about initforms which depend on side effects, if they want to achieve portability. > When more than one class in the CPL specifies a default value >form for a given initarg, only the form specified by the earliest such class in ^^^^^^^^ >the CPL is used. Suggest use of "most specific", since "earliest" could be interpreted either way. >The primary method for INITIALIZE-INSTANCE is system-supplied and takes care >of the slot-filling initargs. For each slot (whether local or shared): > > - if an initarg was specified or defaulted that fills that slot, its > value is stored into the slot. > > - otherwise, if the slot is uninitialized and it has an initform, the > initform is evaluated and the result is stored into the slot. > > - the duplicate-resolution rules mentioned earlier are obeyed. Something needs to be said here about the case where a user writes a :BEFORE method and SETF's the slot there. From the rest of the text, it sounds as if INITIALIZE-INSTANCE is permitted to clobber that slot. This makes :BEFORE methods on INITIALIZE-INSTANCE less then useful for slot initialization. The result requires either that INITIALIZE-INSTANCE be singled out in a particular way to prohibit :BEFORE methods, or allows the system to arbitrarily clobber something the programmer has done. One way out of this dilemma is to simply have the :BEFORE method and the :AROUND method for INITIALIZE-INSTANCE be reserved for the system. Similarly for the :AFTER and :AROUND methods of ALLOCATE-INSTANCE. This would leave no places where user defined hooks could be inserted before the INITIALIZE-INSTANCE primary is run. Users redefine these qualified methods at their own peril, as is the case with redefining any system defined method (or function for that matter). >Do you think it would be worth trying a version of the writeup that uses >CLtL's terminology, with a simple admonition that a "keyword name" is not >necessarily a keyword symbol? Yes, this would be a good idea. I think a case can be made for a semantic distinction between keyword symbols and keyword arguments. The term keyword argument is used in Smalltalk as well, where the concept of keyword symbols does not occur. 4) On method combination types: > CALL-NEXT-METHOD is supported in :AROUND methods only. .... >An error is signaled if CALL-NEXT-METHOD is used in a primary method. In primaries as well???? If so, then we're talking about a major change, because 87-002 allows it in primaries. Or perhaps this is only for the new method combination types? If so, then I'd be interested in a reason for prohibiting method combination in primaries, since it introduces a major incompatibility between different types of method combination. 5) On :INSTANCE v.s. local: Either way is OK. 6) On DEFMETHOD syntax changes: Good. 7) On NEXT-METHODS: The primary reason is for being able to tell if calling CALL-NEXT-METHOD would signal an error. I understand Masinter's concern, and wonder if perhaps it might not be better to handle this with Ken Pitman's error proposal. Other than finding out whether a call to CALL-NEXT-METHOD is valid, there isn't much use for the list of next methods, as Masinter has pointed out. 8) On changing the names of built-in classes: Good. 9) On SLOT-UNBOUND: Good. 10) On NO-APPLICABLE-METHOD: >( no-applicable-method generic-function first-argument &rest >all-arguments) I thought we had agreed to get rid of the first argument kludge. Otherwise, this is the only place in the entire spec where we're making a distinction between multiple dispatch object oriented programming and classical object oriented programming. The user has to go through some additional grief if all the arguments are passed as an &REST parameter in order to get forwarding, but I think that forwarding should best be left to metaobject programmers anyway, since it is, as yet, experimental (neither PCL nor New Flavors have it). Someone could write a forwarding metaobject method as: (defmethod no-applicable-method ( (gf forwarding-generic-function) &rest all-arguments ) (apply #'forward-method all-arguments) ) A user can do something similar with the default method, with somewhat hairier code. I think the primary reason people using the default CLOS language (as opposed to the metaobject protocol) would want all the arguments anyway is to print a more informative error message. There are a couple of additional issues which will require specific longer responses. I'll mail these out today. jak  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 28 Sep 87 09:37:06 EDT Received: from CS.UTAH.EDU by SAIL.STANFORD.EDU with TCP; 28 Sep 87 06:23:42 PDT Received: by cs.utah.edu (5.54/utah-1.0) id AA12716; Mon, 28 Sep 87 07:23:27 MDT Received: by orion.utah.edu (5.54/utah-1.0-slave) id AA05499; Mon, 28 Sep 87 07:23:17 MDT Date: Mon, 28 Sep 87 07:23:17 MDT From: muehle%orion@cs.utah.edu (Eric Muehle) Message-Id: <8709281323.AA05499@orion.utah.edu> To: common-lisp-object-system@sail.stanford.edu Subject: remove me from the list muehle@orion.utah.edu ERIC  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 26 Sep 87 19:51:49 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Sep 87 16:39:50 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 26 SEP 87 16:40:22 PDT Date: 26 Sep 87 16:40 PDT From: Masinter.pa@Xerox.COM Subject: Re: Amendments requiring additional writing In-reply-to: David A. Moon 's message of Fri, 25 Sep 87 21:41 EDT To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870926-164022-17885@Xerox> While fixing typep and subtypep to deal with classes seems likely to preferable to adding instancep and subclassp, attempting to fix type-of so that it sometimes returns a class and sometimes returns a symbol seems hopeless, and bad design. type-of is so underconstrained in any case to be worthless. I think you're better off abandoning it -- e.g., implementations can return T if on instances of classes if they need to. The proponents for disallowing careless name->value mappings will likely be unhappy with the polymorphic typep and subtypep; it might be useful to be able to lexically determine whether they might be used in a given program. Does anyone else see a linkage between the function-type proposal and the form for typep/instancep subtypep/subclassp type-of/class-of?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 25 Sep 87 21:55:38 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Sep 87 18:40:49 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 242001; Fri 25-Sep-87 21:41:23 EDT Date: Fri, 25 Sep 87 21:41 EDT From: David A. Moon Subject: Amendments requiring additional writing To: Common-Lisp-Object-System@SAIL.STANFORD.EDU Message-ID: <870925214129.4.MOON@EUPHRATES.SCRC.Symbolics.COM> I looked through the Amendments handed out at the March X3J13 meeting, with an eye to Dick's comments that some of them couldn't just be edited into the document, but required significant additional writing. Here is suggested writing for the ones that don't already have suggested writing. There might also be a problem of the suggested writings being hard to understand, inappropriate, or incorrect; if so, we should discuss those over the mail. 1-11: Replace the last paragraph with the following two paragraphs: If in the new version of the class there is a local slot of the same name as any slot in the old version of the class, the value of that slot will be the same in both instances. This means that if the slot has a value, the value returned by {\bf slot-value} after {\bf change-class} is invoked is {\bf eql} to the value returned by {\bf slot-value} before {\bf change-class} is invoked. Similarly, if the slot was uninitialized, it remains uninitialized. At the moment a class is redefined, if the new version of the class contains a shared slot of the same name as any shared slot in the old version of the class, the value of that slot will be the same in both. If in the new version of the class there is a shared slot of the same name as any local slot in the old version of the class, that shared slot is initialized to the value of the corresponding {\bf :initform} option of the new class, or remains uninitialized if the new version of the class does not specify or inherit the {\bf :initform} option for that slot. Shared slots are not affected by the updating of an instance. [1-11 will also get some changes to reflect the new scheme for redefining classes, which does not use change-class, and some of the existing text will be recycled as a description of change-class, however I'm not trying to address those here.] 2-54: subtypep Function Purpose: The Common Lisp function {\bf subtypep} is extended to accept class objects as type-specifiers. Syntax: {\bf subtypep} {\it type1} {\it type2} Arguments: {\it type1} and {\it type2} are type specifiers of any kind, including class objects. Values: The first value is {\it true} if {\it type1} is definitely a (not necessarily proper) subtype of {\it type2}. The second value indicates the certainty of the result. type-of Function Purpose: The Common Lisp function {\bf type-of} is extended to accept an instance of any class as its argument. For instances of standard classes, {\bf type-of} returns the class name when one exists, otherwise the class object. Syntax: {\bf type-of} {\it object} Arguments: {\it object} is any object. Values: The result is a type-specifier such that {\bf (typep {\it object} '{\it result})} is true. If {\bf (class-of {\it object})} is an instance of {\bf standard-class}, {\bf type-of} behaves as if it was defined by \screen! (defun type-of (object) (let* ((class (class-of object)) (class-name (class-name class))) (if (and class-name (cboundp class-name) (eq (symbol-class class-name) class)) class-name class))) \endscreen! typep Function Purpose: The Common Lisp function {\bf typep} is extended to accept class objects as type-specifiers. Syntax: {\bf typep} {\it object} {\it type} Arguments: {\it object} is any object. {\it type} is a type specifier of any kind, including a class object. Values: The value is {\it true} if {\it object} is of type {\it type}.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 25 Sep 87 16:10:33 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Sep 87 12:58:09 PDT Received: from relay2.cs.net by RELAY.CS.NET id ad14604; 25 Sep 87 14:32 EDT Received: from ti-csl by RELAY.CS.NET id af18322; 25 Sep 87 14:14 EDT Received: from Jenner by tilde id AA14104; Tue, 22 Sep 87 09:33:34 CDT Message-Id: <2768308570-8410382@Jenner> Date: Tue, 22 Sep 87 09:36:10 CDT From: Patrick H Dussud To: Gregor.pa@XEROX.COM Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU Subject: Re: fixing our problems with setf In-Reply-To: Msg of 20 Sep 87 19:03 PDT from Gregor.pa@xerox.com Date: 20 Sep 87 19:03 PDT From: Gregor.pa@xerox.com Subject: fixing our problems with setf Unless we can get setf 'fixed' in the entire language, I propose that we solve our problems with setf by eliminating all the setf features from CLOS (except automatically generated writer methods). That means get rid of the ability to say (setf ) to defmethod, symbol-function, generic-function-labels, generic-flet and the others. My belief is that we are geting into trouble because we are confusing (generic) function naming with defining setf macros. This gets us screwed because setf is a macro in yet another namespace and doesn't interact real well with our stuff. Put another way, there isn't (right now) anything called defun-setf. If you want to do that you have to do (something like): (defsetf foo |setf FOO|) (defun |setf FOO| (x new-value) ...) Given that, I don't see whats so wrong with having to do: (defsetf bar |setf BAR|) (defmethod |setf BAR| ((x boat) new-value) ..) The problem is that we can't always specialize on the new-value argument using the short defsetf form. The programmer will have to write a hocky defsetf form to get around the problem of having optional arguments (e.g. implementing the setf form of SUBSEQ as a generic function). We lose the COMBINE-LAMBDA-LISTS abstraction. I agree with Masinter, if we don't propose a fix, nobody will fix it. Our haste of finishing the specs shouldn't make us adopt a short term view when we know what the long term solution should be. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 25 Sep 87 15:21:46 EDT Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 25 Sep 87 12:08:26 PDT Received: from relay2.cs.net by RELAY.CS.NET id ab14626; 25 Sep 87 14:34 EDT Received: from ti-csl by RELAY.CS.NET id ap18322; 25 Sep 87 14:17 EDT Received: from Jenner by tilde id AA16860; Tue, 22 Sep 87 11:22:12 CDT Message-Id: <2768315111-8803361@Jenner> Date: Tue, 22 Sep 87 11:25:11 CDT From: Patrick H Dussud To: common-lisp-object-system@SAIL.STANFORD.EDU Subject: Exact type I have second thoughts about allowing any common lisp type in (declare (exact-type ...)) - First, what does exact-type means? Since type-of cannot be trusted to return the most specific type an object is of, we have to base our definition on TYPEP. I propose this one: x is of exact-type X if it verifies: Let Y be a type such as (SUBTYPEP X Y) is true, then (TYPEP x Y ) is false. I think it does what JAK meant. - Assuming that my definition is correct, for which type does it make sense? It makes sense for our classes since all the subclasses can be known, they are user classes. By the same token, it makes sense for defstruct types. But allowing the other COMMON subtypes would makes programs non portable: The list of subtypes of a type is implementation dependent. We say (page 1-14) that individual implementation can add additional subclass relationships as long as they don't violate CLtL. I propose that we restrict the types acceptable to (declare (exact-type ...)) to CLOS classes and structure types. Patrick.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 23:48:39 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 20:34:44 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 241155; Thu 24-Sep-87 23:35:55 EDT Date: Thu, 24 Sep 87 23:35 EDT From: David A. Moon Subject: Redefining Classes To: Common-Lisp-Object-System@Sail.stanford.edu In-Reply-To: <870924-091259-15052@Xerox> Message-ID: <870924233529.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 24 Sep 87 09:12 PDT From: Bobrow.pa@Xerox.COM Redefining Classes This is okay for the most part, but I have a few comments to offer on excerpts from your proposal. There are a few areas that need to be tightened up, plus one major defect. I'll conclude with a somewhat random comment about multiprocess systems. If the redefinition of a class causes the structure of its instances to be different... I think we're going to have to define this more precisely. I see two options: (1) Adding or removing an instance slot definitely changes the structure, and some other operations may also change the structure, depending on the implementation. (2) The structure changes if and only if the value of (class-all-instance-slot-names class) is not EQUAL to its previous value. I made up the function name class-all-instance-slot-names, but you get the idea. Note how class-all-slot-names won't work. The big difference between option 1 and option 2 is that with option 2, a given sequence of defclass forms will produce exactly the same sequence of calls to make-instances-obsolete in all implementations. I'm inclined to option 2, because it is more precise, but I'm worried that this might rule out some implementation possibility. Also, for this to be meaningful and portable, we have to define the exact order of slots produced by slot inheritance, which is not something we've had to specify before now. Obsolete instance updating is done in two stages: 1) The system creates a property list that captures the slot names and values of all the slots of the obsolete instance. It then transforms the structure of the instance, so that it conforms to the current class definition. All the slots of this transformed instance are uninitialized. This first stage cannot be seen by user programs. 2) The generic function update-obsolete-instance is called. Its arguments are the transformed instance, and the property list of slot-names and values corresponding to the state of the obsolete instance. Its contract is to do appropriate updating of the instance, using the values from the obsolete slots. I have two problems with this. The easy problem is that I don't like the name update-obsolete-instance, because the instance doesn't really seem obsolete to me. One idea is to take an analogy to class-changed and call it class-redefined. In Flavors we call it transform-instance, but it doesn't have quite the same semantics. It's likely that someone can think of a better name than any of these. Much more important, I can't implement the specification that the slots are initially uninitialized and then they are filled in from values saved in a property list. There are two problems, one obvious and one subtle. The obvious problem involves slots that were unbound originally; since there is no Lisp value that means "unbound", there is nothing that can be put into the property list for these slots. But if we don't put any entry in the property list, then the desired feature that the method can tell which slots were added or removed is lost; these slots look like they were added, even though they weren't. Also, the default method you mention below will put the :initform value into these previously unbound slots, which seems wrong. "Unbound" should not be confounded with "nonexistent." The subtle problem involves some language extensions that we have, allowing slots to have contents that cannot be expressed as Lisp values in a property list. For instance, there is a mechanism similar to Prolog logic-variables which allows two slots to be linked together. This linkage has to be preserved in the face of class redefinition. For these reasons, I believe it is better to specify that the slot values are conveyed from the old structure of the instance to the new structure by the low-level implementation, not by a user-replaceable method. Thus when the generic function update-obsolete-instance is called, all slots that existed in the old class definition, and existed as instance slots in the new class definition, already have their values, as the same low-level bits. I can't see any need for even a meta-user to replace this with something else. Now we have to ask what information the update-obsolete-instance method needs. If I remember last week's discussion, the idea of passing in a property list was that it contained the set of old slots, and by querying the class one could get the set of new slots, and thus the added and deleted slots could be determined. Unfortunately unbound slots break this, since either they can't have property list entries or the property list entry has to contain a made-up value. I suggest conveying the desired information directly, rather than trying to be clever: Give update-obsolete-instance four arguments: the instance a list of the names of all added slots a list of the names of all deleted slots a property list giving the values of all deleted, bound slots I think this conveys all relevant information directly, and it's probably less consing than the full property list. Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. We're going to have to specify this a little more precisely, I suspect. We should specify when is the latest time that an implementation can call update-obsolete-instance, and then say that it is permitted to call it any time earlier (after the class has been redefined). I now believe that the latest time can simply be the time any of the four slot access and modification functions (or internal equivalent) is called, in spite of all the flaming against this we engaged in while discussing Danny's proposal at the meeting last week. The method on update-obsolete-instance defined on the class Object does the following... Instead, I would say the default method initializes only the newly added slots. Multiprocess systems are going to have to be careful about what happens if other processes access the object before update-obsolete-instance returns. I don't like the way Flavors does this now, which is: allocate any new storage and evaluate any necessary initforms; with other processes locked out, check again that the instance is still obsolete, then convey the slots to the new storage and link things up, now with processes running freely again, call the user's methods. Maybe the user's methods should run with other processes locked out, especially if newly added slots are only initialized by these methods. Of course CLOS doesn't have to say anything about the extension to multiple processes.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 19:02:20 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 15:49:07 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 15:49:38 PDT Date: 24 Sep 87 15:49 PDT From: Masinter.pa@Xerox.COM Subject: Re: next-methods In-reply-to: Gregor.pa's message of 24 Sep 87 14:56 PDT To: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-154938-15779@Xerox> Even if there are implementations in which it is easy, my original question stands: when would you use such a thing? Its just not in the list of 20 obvious things that I can imagine wanting to get hold of.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 18:11:56 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 14:58:30 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 14:56:32 PDT Date: 24 Sep 87 14:56 PDT From: Gregor.pa@Xerox.COM Subject: Re: next-methods In-reply-to: David A. Moon 's message of Thu, 24 Sep 87 14:41 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Masinter.pa@Xerox.COM, Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-145632-15708@Xerox> I suspect that the implementation I envision is a lot like the one Moon does. I can't see any reason why implementing next-methods would be harder than call-next-methods.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 14:55:25 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 11:41:52 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240696; Thu 24-Sep-87 14:42:04 EDT Date: Thu, 24 Sep 87 14:41 EDT From: David A. Moon Subject: Re: next-methods To: Masinter.pa@Xerox.COM cc: Common-Lisp-Object-System@Sail.stanford.edu In-Reply-To: <870924-105219-15293@Xerox> Message-ID: <870924144150.1.MOON@EUPHRATES.SCRC.Symbolics.COM> Line-fold: No Date: 24 Sep 87 10:52 PDT From: Masinter.pa@Xerox.COM What's next-methods for? I'm having trouble imagining a use, and no trouble imagining difficulties implementing it. In particular, it means that you need to provide access to the entire list of subsequent methods rather than just the next one. In my envisioned implementation the list would not be materialized unless someone actually called next-methods, and I think none of the mechanism would be present unless there was actually a lexical reference to next-methods. That is, the generic function works slightly differently if somewhere in the effective method, next-methods is used. Much the same thing will be done for call-next-method. If I hadn't been thinking along those lines, I might have made the same objection you raised.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 14:37:42 EDT Date: 24 Sep 87 1124 PDT From: Dick Gabriel Subject: NEXT-METHODS To: common-lisp-object-system@SAIL.STANFORD.EDU Larry writes: ``What's next-methods for?'' Among other things, it's so that a program can know whether call-next-method will signal an error the next time around. I think there is a second reason for it, which is to provide some window onto the hidden state within a generic function. -rpg-  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 14:03:57 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:51:47 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 10:52:19 PDT Date: 24 Sep 87 10:52 PDT From: Masinter.pa@Xerox.COM Subject: Re: next-methods In-reply-to: Bobrow.pa's message of 24 Sep 87 09:03 PDT To: Bobrow.pa@Xerox.COM cc: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-105219-15293@Xerox> What's next-methods for? I'm having trouble imagining a use, and no trouble imagining difficulties implementing it. In particular, it means that you need to provide access to the entire list of subsequent methods rather than just the next one.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 13:33:35 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:21:24 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 10:20:09 PDT Date: 24 Sep 87 10:19 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: Terminology: Shared versus class; local versus instance In-reply-to: David A. Moon 's message of Thu, 24 Sep 87 12:43 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: Common-Lisp-Object-System@sail.stanford.edu Message-ID: <870924-102009-15244@Xerox> Note that by recourse to old documents you can discover that the term "local slot" was introduced to cover both ":allocation :instance" and ":allocation :dynamic" slots. No doubt the existence of :dynamic meant that it would have been confusing to call these "instance slots". Now that :dynamic is gone, it would be okay with me to simplify things by calling the two kinds of slots "instance" and "class". Do you think that this terminological change might cause trouble for implementations that experiment with extensions, such as dynamic slots? No, because one could use "instance or dynamic" to cover the union. The name now is specific to the specified allocation rather than to a property of that allocation. (Of course one might wonder in this connection why no one ever proposed dynamic class slots, in other words, why the static/dynamic distinction was thought to be on the same axis as the local/shared distinction.) Dynamic slots were proposed as an efficiency measure for slots that were seldom used, the argument was that it was better not to allocate space in each instance. For class slots, allocation is only once per class. danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 13:12:51 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 10:01:29 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240560; Thu 24-Sep-87 13:02:43 EDT Date: Thu, 24 Sep 87 13:02 EDT From: David A. Moon Subject: Re: September version of object-creation (More nits) To: Danny Bobrow cc: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: <870924-094503-15151@Xerox> Message-ID: <870924130228.9.MOON@EUPHRATES.SCRC.Symbolics.COM> Line-fold: No Date: 24 Sep 87 09:44 PDT From: Danny Bobrow METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS (returns a list of keyword names, not parameter specifiers) Then this should be called METHOD-KEYWORD-NAMES, n'est pas? Mais oui.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 13:10:17 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:56:34 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240552; Thu 24-Sep-87 12:57:44 EDT Date: Thu, 24 Sep 87 12:57 EDT From: David A. Moon Subject: slot-missing To: Common-Lisp-Object-System@Sail.stanford.edu In-Reply-To: <870924-092749-15093@Xerox> Message-ID: <870924125723.7.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 24 Sep 87 09:27 PDT From: Bobrow.pa@Xerox.COM The generic function slot-missing is called by slot-value-using-class (setf slot-value-using-class) slot-bound-p For each of these operations the corresponding symbol for the operation argument is slot-value setf slot-boundp That should be The generic function slot-missing is called by slot-value-using-class (setf slot-value-using-class) slot-boundp-using-class slot-makunbound-using-class For each of these operations the corresponding symbol for the operation argument is slot-value setf slot-boundp slot-makunbound Otherwise it's fine.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 13:02:51 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:51:11 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:45:03 PDT Date: 24 Sep 87 09:44 PDT Sender: Bobrow.pa@Xerox.COM From: Danny Bobrow Subject: Re: September version of object-creation (More nits) In-reply-to: David A. Moon 's message of Thu, 24 Sep 87 12:38 EDT To: Moon@STONY-BROOK.SCRC.Symbolics.COM cc: common-lisp-object-system@SAIL.STANFORD.EDU Message-ID: <870924-094503-15151@Xerox> METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS (returns a list of keyword names, not parameter specifiers) Then this should be called METHOD-KEYWORD-NAMES, n'est pas? danny  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:54:43 EDT Received: from [128.81.41.234] by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:42:36 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by MEAD.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 95280; Thu 24-Sep-87 12:43:30 EDT Date: Thu, 24 Sep 87 12:43 EDT From: David A. Moon Subject: Terminology: Shared versus class; local versus instance To: Common-Lisp-Object-System@sail.stanford.edu In-Reply-To: <870923-085147-13566@Xerox> Message-ID: <870924124333.6.MOON@EUPHRATES.SCRC.Symbolics.COM> Either terminology would be okay with me, as long as they are used consistently. Note that by recourse to old documents you can discover that the term "local slot" was introduced to cover both ":allocation :instance" and ":allocation :dynamic" slots. No doubt the existence of :dynamic meant that it would have been confusing to call these "instance slots". Now that :dynamic is gone, it would be okay with me to simplify things by calling the two kinds of slots "instance" and "class". Do you think that this terminological change might cause trouble for implementations that experiment with extensions, such as dynamic slots? (Of course one might wonder in this connection why no one ever proposed dynamic class slots, in other words, why the static/dynamic distinction was thought to be on the same axis as the local/shared distinction.)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:50:02 EDT Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:37:38 PDT Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 240528; Thu 24-Sep-87 12:38:48 EDT Date: Thu, 24 Sep 87 12:38 EDT From: David A. Moon Subject: September version of object-creation (More nits) To: common-lisp-object-system@SAIL.STANFORD.EDU In-Reply-To: The message of 24 Sep 87 01:02 EDT from Dick Gabriel Message-ID: <870924123827.5.MOON@EUPHRATES.SCRC.Symbolics.COM> Date: 23 Sep 87 2202 PDT From: Dick Gabriel In 87-002, we have tried to use the term ``parameter'' to refer to the thing that appears in a lambda-list and ``argument'' to refer to the thing that gets passed to the lambda-expression. In the writeup of initialization, we (that is, whoever writes it) ought to be careful to keep this disctinction in mind. I think it is ok to call the things :initargs and the like if we are careful. Agreed completely. In the latest version I mailed out, I made some effort to straighten this out, however I think additional effort is likely to be needed. I just re-read CLtL pp.61-3. The stickiest terminological problems in my writeup have to do with finding replacements for CLtL's terms "keyword parameter" and "keyword name" that don't contain the word "keyword". CLtL uses "keyword name" in connection with both arguments and parameters, so you can see where my attempt to substitute "named-argument name" runs into trouble. Do you think it would be worth trying a version of the writeup that uses CLtL's terminology, with a simple admonition that a "keyword name" is not necessarily a keyword symbol? After all, CLtL also has "lambda list keywords", so maybe "keyword" in Common Lisp means "any symbol that identifies a syntactic position" rather than "(eq (symbol-package symbol) (find-package 'keyword))". I surveyed the writeup and it looks like the changes would be these: named argument -> keyword argument named argument name -> keyword name "initarg name" remains unchanged named-parameter name -> keyword parameter specifier's keyword name (wordy, but CLtL doesn't seem to use a shorter term for this) METHOD-NAMED-PARAMETERS -> METHOD-KEYWORD-PARAMETERS (returns a list of keyword names, not parameter specifiers) Opinions?  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:39:20 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:27:18 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:27:49 PDT Date: 24 Sep 87 09:27 PDT From: Bobrow.pa@Xerox.COM Subject: slot-missing To: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-092749-15093@Xerox> slot-missing If an attempt is made to access a slot in an instance of a standard class, and the name of the slot provided is not a name of a slot in that class, then the generic function slot-missing is invoked. slot-missing class instance slot-name operation &optional new-value The required arguments to slot-missing are the class of the instance being accessed, the instance, the slot-name, a symbol that indicates the operation which caused the trap to slot-missing. The optional argument to slot-missing is used when the operation is attempting to set the value of the slot. The generic function slot-missing is not intended to be called by programmers. Programmers are expected to write methods for it. The generic function slot-missing is called by slot-value-using-class (setf slot-value-using-class) slot-bound-p For each of these operations the corresponding symbol for the operation argument is slot-value setf slot-boundp The default method on slot-missing signals an error. This set of arguments (including the class of the instance) facilitates defining methods on the metaclass for handling slot-missing. For example, this enables an easy implementation of dynamic slots; that is: (defmethod slot-missing ((class dynamic-class) obj slot operation &optional nv) (ecase operation (slot-value (get-dynamic-slot obj slot)) (setf (set-dynamic-slot obj slot nv) (slot-boundp (exists-dynamic-slot-p obj slot))))  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:31:09 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:17:36 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:18:08 PDT Date: 24 Sep 87 09:17 PDT From: Bobrow.pa@Xerox.COM Subject: Unbound Slots To: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-091808-15069@Xerox> NOTE: The name slot-uninitialized has been changed to slot-unbound Not all slots in an instance need to be bound. This can happen if a slot has no :initform, an has not been set, or if the user has called slot-makunbound. Referencing an unbound slot of an instance of a standard class causes the generic-function slot-unbound to be invoked. The arguments to slot-unbound are the same as the arguments to slot-value-using-class, that is, the class of the instance whose slot was accessed, that instance, and the name of the slot. The generic function slot-unbound is not intended to be called by programmers. Programmers are expected to write methods for it. The function slot-unbound is called only by the function slot-value-using-class. slot-unbound class instance slot-name (generic function) The slot-unbound method on standard-class signals an error.  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:30:49 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:18:54 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:19:27 PDT Date: 24 Sep 87 09:19 PDT From: Bobrow.pa@Xerox.COM Subject: DRAFT: Changing Names of Built-in classes To: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-091927-15071@Xerox> The class associated with a particular symbol can be changed by using setf with the accessor symbol-class. It is undefined what happens if the user attempts to change the class associated with a symbol that is defined as a type specifier in CLtL. e.g. (SETF (SYMBOL-CLASS 'CONS) ...)  Received: from SAIL.STANFORD.EDU (TCP 1200000013) by AI.AI.MIT.EDU 24 Sep 87 12:29:04 EDT Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Sep 87 09:15:37 PDT Received: from Cabernet.ms by ArpaGateway.ms ; 24 SEP 87 09:12:59 PDT Date: 24 Sep 87 09:12 PDT From: Bobrow.pa@Xerox.COM Subject: Redefining Classes To: Common-Lisp-Object-System@Sail.stanford.edu Message-ID: <870924-091259-15052@Xerox> Redefining Classes When a defclass form is evaluated and a class with the given name already exists, the existing class is redefined. This may also cause some of the subclasses of the redefined class to also be redefined. Classes my also be redefined using the metaobject protocol -- see the functions add-named-class and update-class. For instances of standard-class, redefining a class modifies the existing class object to reflect the new class definition; it does not create a new class object for the class. Any method created by an :accessor, :reader, specified by the old defclass form is removed from the corresponding generic function unless that same method is specified by the new defclass form. If the redefinition of a class causes the structure of its instances to be different, and the class has instances, then the generic function make-instances-obsolete is called. The function make-instances-obsolete takes as its one argument the class to be redefined. This invocation captures the state of the class before redefinition, and marks all existing instances of the class as obsolete. Such instances will be updated to the new structure determined by the class redefinition. This updating will be done in such a way that users will never see an instance with the obsolete structure. THIS IS ONLY GUARANTEED TO BE SUPPORTED FOR CLASSES THAT ARE INSTANCES OF STANDARD CLASS. make-instances-obsolete class (generic-function) Obsolete instance updating is done in two stages: 1) The system creates a property list that captures the slot names and values of all the slots of the obsolete instance. It then transforms the structure of the instance, so that it conforms to the current class definition. All the slots of this transformed instance are uninitialized. This first stage cannot be seen by user programs. 2) The generic function update-obsolete-instance is called. Its arguments are the transformed instance, and the property list of slot-names and values corresponding to the state of the obsolete instance. Its contract is to do appropriate updating of the instance, using the values from the obsolete slots. Because update-obsolete-instance is user code, its operation can be seen by the user; but the model that CLOS supports is that as far as the user can tell, all the existing instances of a class are updated as soon as the class redefinition happens. This implies that the user must define a method for update-obsolete-instance before redefining a class. Implementations are free to delay the conversion of existing instances (for example, to method call or slot access time), but users should never be able to see the untransformed instance. update-obsolete-instance instance property-list (generic-function) The method on update-obsolete-instance defined on the class Object does the following: 1) for each instance slot in current definition of class, if its slot-name appears in the property list, the value corresponding to the slot-n