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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,fa2cc518ef3b992c X-Google-Attributes: gid103376,public From: Mark Lundquist Subject: Re: tagged types extensions - language design question Date: 2000/01/31 Message-ID: <3895EC61.9B2157A8@rational.com> X-Deja-AN: 580029168 Content-Transfer-Encoding: 7bit References: To: vladimir_olenski@yahoo.com Content-Type: text/plain; charset=us-ascii Organization: Rational Software Mime-Version: 1.0 Newsgroups: comp.lang.ada Date: 2000-01-31T00:00:00+00:00 List-Id: Vladimir Olensky wrote: > The question is : > > Why in Ada it is not allowed to extend both public > and private part of the tagged type at one step Good question! None of the heavy hitters (Tucker et al) have weighed in, so let me venture my guess... I'd say the bottom line is, there isn't any really good reason. That's the short answer, stay with me if you want the details... :-) First of all, the way you phrased the question is likely to trip up some people. I think that Ada programmers aren't accustomed to thinking of an abstraction as having a "public" part that is extended by public extensions and a private part that is extended by private extensions. Not that it's incorrect or misleading to think that way in Ada; it's just that the way the language is defined doesn't encourage you to think in those terms. The way of thinking that's "natural" to Ada is to think of the derived type as providing an extension to the parent type, which extension is either public or private. So a more Ada-natural way to phrase your question might be, "why is there no syntax that combines both a public and private type extension?" But watch how this develops.. it gets deeper and more interesting! Onward to your example... > ( using > kind of syntax as in the following example ): > > package P is > > type T is tagged private; As others have pointed out, type T cannot be extended at this point because its full declaration isn't available. But I get the impression that T's being declared in P is not essential to your example. That is, you aren't concerned with the fact that T really has to come from another package. What you care about is that extending it in the way you want is going to require two type declarations, one to declare a public extension and another to declare the private extension. The first of these declarations is just "intermediate", in the sense that its only purpose is to be derived from by the second. You are just wondering why there couldn't have been a more streamlined way to do this in Ada, right? > type T1 is new T with > record with private > something: some_type; > and record; One possible reason could have been that there wasn't any good syntax for the feature. Good syntax would have to be clear to human readers, technically unambigous, and consistent with the rest of Ada. If the benefit of the feature would have been marginal, but the feature carries a cost of nastified syntax, then that feature is probably not going to make it into the language. For this reason, it's a worthwhile exercise to explore different syntax alternatives for features that you think should have gone into the language, or that you would like to see added to the language in the future. Sometimes the exercise exposes the fact that the feature doesn't really make sense after all. Other times, it can be a "proof by construction" that a good syntax is available, and that arguments against the feature on "no good syntax" grounds are unsound! So I will note in passing that in your example quoted above, having the record component list follow "with private" is poor, because it seems to say that "private" applies somehow to the list of components. A better alternative might be type T1 is new T with private with record Something_Public: Whatever; end record; This is clearer, because there is no "parenthetical" thing interposed between "record" and "end record". > > > private > > type T is tagged with > record > ID : Integer; > end record; > > type T1 is new T with > record > thing : some_other_type; > end record; > > end P; One of the rules of Ada syntax that you probably won't be able to break is that the full type declaration that completes a private type declaration (or extension declaration) has to be just that, _full_. In other words, you could remove the private type declaration and just _move_ the full declaration from the package private part to the visible part, and that would suffice to make the type visible. So for instance, if your private type declaration has (known) discriminants, then they have to be duplicated in the full type declaration. So your example syntax is no good because it in fact declares a completely different type, rather than completing the private declaration. It would at least have to say _something_ about the public part, and the most obvious thing, and also the way that would be most consistent with the existing feel of Ada, would be to duplicate it. Now, when you start trying to come up with a syntax that does this cleanly, you end up with something like this: type T1 is new T with record Something_Public: Whatever; private Something_Private: Whatever; end record; Now it becomes somewhat of a stretch to think of this as a syntax that combines a public extension and a private extension. We really now have to think of it as an extension that has both public and private components, and we were really committed to this once we decided to allow this in a single type derivation (it makes more sense to have one extension per derivation, after all... not two!) So if we change the language this way, we nullify 3.9.1(1) and change the definition of a type extension to something that in the general case has public and private components. This is really interesting. First of all, consider the full type declaration "rule" that I described earlier: the type extension shown above should be legal in the visible part, as well as the private part! And there is nothing that should really prevent this, since the private parts are private by virtue of the "private" in the extension -- it no longer depends on being in the private part of the package. All of this really begs the question of why this should be restricted to only extensions. Why should a simple tagged or non-tagged record declaration not also be able to have private components?: type Foo is record Public_Stuff: Whatever; private Private_Stuff: Whatever; end record; The syntax of protected declarations also is a precedent for this. Moreover, this takes us full circle to one of the original non-issues of not being able to extend a private or privately-extended type in the same package in which it's declared! If went all the way and allowed private components within a record declaration, the full type is now available within the visible part, and you can derive from it, if it makes sense logically to do it there! (i.e. the closely-related abstraction thing). So that allows packages to serve us naturally in one more situation, rather than forcing us to serve packages :-) So I think the real question is not, why can't you extend publicly and privately "all at once", but rather, why not let records and extensions have private components? It seems clear that any compromise of 3.9.1(1) is a very slippery slope that shoots you straight down to this. As I said before, I don't see any compelling reason why this couldn't have or shouldn't be done. Is there a compelling reason to do it (or to have done it)? I don't know. You could probably make a pretty good case for it. Back to "reality" :-)... > Instead I should do this in two steps. > 1. to extend private part and then > 2. to extend public part > or vice versa. > Right. Note that the first derived type can be abstract, which clarifies your intent. > Due to that type T1 has inheritance_depth = 3 > instead of inheritance_depth = 2. > Yeah... is there a problem with that? Cheers! Mark Lundquist Rational Software