From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=BAYES_00,FORGED_MUA_MOZILLA autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,81bb2ce65a3240c3 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.204.157.134 with SMTP id b6mr2415203bkx.5.1336504822995; Tue, 08 May 2012 12:20:22 -0700 (PDT) Path: h15ni89bkw.0!nntp.google.com!news1.google.com!news3.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: What would you like in Ada202X? Date: Tue, 08 May 2012 22:20:21 +0300 Organization: Tidorum Ltd Message-ID: References: <3637793.35.1335340026327.JavaMail.geo-discussion-forums@ynfi5> <172r5u18q2247.ze0a856uvhqt.dlg@40tude.net> <1nmd7pjdxlzs1.cwtljox0244r.dlg@40tude.net> Mime-Version: 1.0 X-Trace: individual.net xo/b2tixOhimocZJLT/70AptrSG0HMN5/JCR5/272ehGvUW3o0aFcND7snE5IqmbwH Cancel-Lock: sha1:aCncgwxNmqH2uqcBkciaB0Xua2k= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Date: 2012-05-08T22:20:21+03:00 List-Id: On 12-05-08 12:03 , Dmitry A. Kazakov wrote: > On Tue, 08 May 2012 02:18:28 +0300, Niklas Holsti wrote: > >> On 12-05-07 10:49 , Dmitry A. Kazakov wrote: >>> On Mon, 07 May 2012 00:26:52 +0300, Niklas Holsti wrote: >>> >>>> On 12-05-06 22:28 , Dmitry A. Kazakov wrote: >>>>> >>>>> Yes, for tagged types operations which are unsafe to inherit are inherited >>>>> abstract, e.g. functions returning covariant value. >>>> >>>> The same could be done also for extension by deepening, but it is not >>>> needed, as long as we don't introduce tags and class-wide programming >>>> for these types. Inheriting these operations as abstract could even be >>>> inconvenient, since it would force the program to implement (override) >>>> the operations even when they are not needed. >>> >>> What are you going to do with user-defined operations? >> >> As distinct from what? Predefined operations? Why should there be any >> difference? > > Because if you inherit them, you get all substitutability problems you > wished to avoid: > > procedure Foo (X : out Message_Kind1) is > begin > X := Request; > end Foo; > > But you already answered below than you want to disallow all out and in-out > operations. Yes, so Foo would not be inherited under that strict rule. Perhaps the derived "deepened" type could inherit operations with "out" and "in out" parameters of the parent type if these parameters were kept as parent type, and not mapped to the derived type (I see that you bring this up later below). For example (referring to the types Message_Kind1 and Detailed_Message_Kind in my first posting), we could have: function Converse (Msg : Message_Kind1) return Message_Kind1 is begin case Msg is when Sign_On => return Sign_Off; when Request => return Reply; when Reply => return Request; when Sign_Off => return Sign_On; end case; end Converse; This function could be inherited (a bit weakly, perhaps) by Detailed_Message_Kind with the profile function Converse (Msg : Detailed_Message_Kind) return Message_Kind1 For example, Converse (Detailed_Message_Kind'(Read)) would return Message_Kind1'(Reply), because Read "is a" Request. If necessary, the user could write a fully "deepened" function: function Converse (Msg : Detailed_Message_Kind) return Detailed_Message_Kind is ... when Read => return Data; ... end Converse; This Converse would be an overloading of the original Converse and the inherited Converse, not an overriding of the latter. But that would be OK, in the absence of class-wide programming. >> My suggestion for derived enumeration types that extend the parent type >> (by "deepening") would create derived types (in the Ada sense), not >> subtypes (in the Ada sense). Thus any user-defined (primitive) >> operations for the parent type (except those with "out" parameters of >> that type, as already discussed) would be inherited (redeclared) for the >> derived type and implemented with automatic conversion of "in" parameters. > > This would exclude all functions returning values of the type. In > particular T'Val, T'Succ, T'Pred. Are you going to define some of them new? Of course the derived "deepened" type must have these operations, since it is an enumeration type, but I would not consider them as "inherited" (except in the sense that the parent type also has operations with the corresponding names and uses). In that sense my wording was inexact and confusing, sorry, and I now understand your question about predefined vs. user-defined operations. I think. T'Val, T'Succ, T'Pred (and T'Image and T'Pos) for a "deepened" type would work as if the "deepened" type were declared as an unrelated enumeration type (by just listing all its literals). >>> they >>> get automatically inherited in any context where visible. [This in effect >>> makes you exposed to "class-wide" programming with subtypes even if you >>> don't want to. All subtypes of a type form a class with ad-hoc operations >>> gathered from all members, when visible.] >> >> Could you give an example, preferably using the types Message_Kind1 and >> Detailed_Message_Kind? > > So far it is clear, except for: > > 1. Distinction between primitive and non-primitive operations. Are all > in-operations primitive (inherited). E.g. > > package P > type Detailed_Message_Kind is new Message_Kind1 ... > end P; > I assume Q (below) has "with P; use P;". > package Q is > procedure Baz (X : Message_Kind1); > ... > end Q; > > with P, Q; use P, Q; > package R is I assume you meant "procedure R is" here. > X : Detailed_Message_Kind; > begin > procedure Baz (X); -- Is this legal? I would say illegal. The potentially inherited operations should be the same as for a derived enumeration type in current Ada, as if the deepened type were defined just as type Detailed_Message_Kind is new Message_Kind1; and the only difference should be the treatment of "out" and "in out" parameters and function return values. > 2. Double-dispatch / multi-methods. What happens with operations which have > several parameters of the parent type: > > procedure Set (X : in out Message_Kind1; Y : Message_Kind1); > > This is inherited in Y, but not inherited in X. Will it become > contravariant in X? E.g. > > procedure Set (X : in out Message_Kind1; Y : Detailed_Message_Kind); Yes, that could be a way to (weakly) inherit operations with "out" or "in out" parameters and function returns. But the consequences of such a rule should be thought out, since it differs from the current Ada inheritance style, as I understand it. > 3. Overriding. If this is the model #2, you can override > > procedure Old (X : Message_Kind1); > > overriding > procedure Old (X : Detailed_Message_Kind); > > Can you? Yes, just as you can override inherited operations on derived enumeration types in current Ada. > This is also related to the question 1. If you can override, you > have multiple dispatch issue, you need freezing rules, you need primitive > and non-primitive in-operations. If you cannot override you may have the > problem that depending on the some contexts one or another operation is > called (weak typing). I'm sure there are complications to sort out. I haven't thought very long or deep about this. If people are interested in this idea, it would motivate some effort on it. I would like to make the "deepening" derivation as similar as possible to the derivation of enumeration types in -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .