Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!apple!agate!shelby!neon!craig From: craig@Neon.Stanford.EDU (Craig D. Chambers) Newsgroups: comp.object Subject: Re: OO Ada -- another way Message-ID: <1990Nov9.010930.26493@Neon.Stanford.EDU> Date: 9 Nov 90 01:09:30 GMT References: <443@eiffel.UUCP> <1990Nov7.220902.13393@Neon.Stanford.EDU> <445@eiffel.UUCP> Organization: Stanford University Lines: 131 In article <445@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes: >From <1990Nov7.220902.13393@Neon.Stanford.EDU> by >craig@Neon.Stanford.EDU (Craig D. Chambers): >>In article <443@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes: >>> This is of course a natural consequence of the view that a class >>>is two things: modular facility and type. This view is applied >>>to its full extent in Eiffel, where there is no other modular facility >>>than the class, and every possible type is based on a class. The >>>rules applying to inheritance (e.g. information hiding rules, the >>>covariant conventions for typing etc.) follow directly. >> >> I disagree that Eiffel's typing rules "follow directly" from treating >> a class as both a module (a collection of method implementations) and >> a type (a set of procedure/function interfaces). >> >> [Various incorrect statements.] >> > > I don't really see the benefit of attributing to someone >(me in this case) comments which are the exact reverse of what >that person actually wrote. This defeats the whole purpose of any >technical discussion - ever more regrettably that other aspects of >Mr. Chambers's posting are worth discussing. What are you saying? That you didn't make the comments that I attributed to you? Of course I included your comments verbatim without editing. I have your original posting (a reply to Ralph Johnson's posting) and my response on line if you'd like to check. Or are you saying that my analysis of Eiffel's "current" (i.e. as described in OOSC) typing rules is opposite of what is really the case? Surely you cannot be saying that Eiffel (OOSC) doesn't have holes in its static checking (even excluding void references). In your posting on comp.lang.eiffel you admit that there is the possibility of getting a run-time error because of Eiffel's (as in OOSC) covariant type rules and its visibility rules; I'd consider this a hole in a static type-checking system. Or are you saying that my interpretation of your recent posting on comp.lang.eiffel for extending the type checker to plug these holes is wrong? Admittedly, I didn't use your words for describing the fix, but (as occurs often in technical discussions) attempted to describe the effect of the change in other terms that reveals it as really something else. I still believe that your proposal is really the same as treating a subclass as a subtype of one of its superclasses iff the arguments of the subclass' methods are the same type as the corresponding argument types of the superclass, and if the visibility declarations are compatible. This gives up any covariant subtyping rules, replacing them with (a restricted form of) contravariant subtyping rules. I made this same observation in an earlier posting on comp.object and comp.lang.eiffel, but didn't get any response to the contrary. If you disagree with this view, then please post a reply with an example illustrating how I'm wrong. Please let me know which statements of mine you consider incorrect, at least by private mail. I can't find the mistakes to which you allude. >> The OrderedCollection problem could be avoided if >> the language includes a default instance of each class (such as a null >> pointer), but null pointers (void references in Eiffel) just introduce >> a whole new class of run-time errors that cannot be detected >> statically (e.g. sending messages to null pointers). > >This is correct, but unfortunately there is no way of dealing with >these errors statically in a typed language that supports references. >(At least there is no practical way unless one is prepared to include >a general-purpose resolution theorem prover in the compiler.) > >Giving up references means giving up linked structures, cyclic ones >etc. This does not seem realistic. If we do have references, then we >need a void reference. Then the possibility of a program attempting to >access a non-existent object (through a void reference) at run-time >exists, and cannot be detected statically in the general case. I strongly disagree that a language with references needs void references. I've always considered them a language design flaw, at least in higher-level languages (e.g. higher than C). See below for examples of languages that do not include void references. >The approach taken by the designers of all languages >supporting references or pointers is that the vacuity question >(whether or not an entity will be void before application of an operation) >has to be resolved at run time. As a consequence vacuity is NOT a >typing property in Pascal, Ada etc. In Eiffel it was felt intellectually >more satisfying to cast this property in typing terms, but the end result >is the same. This is not true. Many dynamically-typed languages exclude void references (e.g. Lisp, Smalltalk). These languages tend to use a nil object, which is tantamount to a void reference, and so are not good counter-examples. In Self we are rewriting our code to avoid using a generic nil object, always initializing variables to "real" objects. In some cases we have type-specific null objects that implement all the messages that should be understood by objects of the type, typically by doing nothing and terminating a recursion. The list-terminating object is a canonical example of a type-specific null object. A statically-typed version of Self could use the same technique to eliminate the need for void references. Some existing statically-typed languages, such as CLU and its successor Trellis/Owl, also exclude void references. In these languages, all variables must be initialized before use. None of these languages requires a run-time vacuity test. >In fact the Eiffel approach may be characterized as follows: all type >checking may be done statically with ONE exception - the vacuity >test. This explains the rationale for the Reverse Assignment Attempt >as described above: in some cases, such as the retrieval of persistently >stored data, a type check must perforce be done dynamically since we >are accessing data over which we have no control, and need to >``clear'' it, in the sense of security clearance, before we start >acting on it as bona fide object-oriented data. We do not, however, >want these (important but infrequent) cases to make static type >checking impossible in all other ``normal'' cases. Then the solution >provided by Reverse Assignment Attempt is to replace a type >check (which should always be static) by the only dynamically checked >property: vacuity. Even assuming that you resolve the holes in the type system by giving up on real covariant subtyping, all you've done here is to replace some static type errors with a single kind of run-time error. This doesn't make those classes of errors go away, just renames them all as vacuity errors. There are still run-time type checks in the system (e.g. for the reverse assignment operator) and potential subsequent run-time errors (e.g. void reference use) which would not be present in a language with complete static type checking (e.g. Trellis/Owl). You may argue that such languages make writing programs too hard, but the existing body of Trellis/Owl software might be a convincing counter argument. -- Craig Chambers