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.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,2e6723b897ab47fb X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.236.83.111 with SMTP id p75mr10989144yhe.5.1344998912269; Tue, 14 Aug 2012 19:48:32 -0700 (PDT) Path: c6ni115589900qas.0!nntp.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nrc-news.nrc.ca!goblin2!goblin.stu.neva.ru!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Ada.Locales pseudo-string types Date: Thu, 9 Aug 2012 18:43:54 +0200 Organization: cbb software GmbH Message-ID: <1jbo845em1fy9.1j45cnfgveye6.dlg@40tude.net> References: <78707b6e-88a3-453a-a37c-840f7a62e703@googlegroups.com> <257b4f44-b6c6-4c79-8c6e-dec947a3ce25@googlegroups.com> <1o3by92cb82px$.1gavjw6p23du6$.dlg@40tude.net> <8zenu4qplfb$.1uc9oi1819c3v$.dlg@40tude.net> <1oel9yro6j0vj.1a64kz67quj9u$.dlg@40tude.net> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: 9A8bJrx4NhDLcSmbrb6AdA.user.speranza.aioe.org Mime-Version: 1.0 X-Complaints-To: abuse@aioe.org User-Agent: 40tude_Dialog/2.0.15.1 X-Notice: Filtered by postfilter v. 0.8.2 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Date: 2012-08-09T18:43:54+02:00 List-Id: On Thu, 09 Aug 2012 18:25:23 +0300, Niklas Holsti wrote: > On 12-08-09 15:17 , Dmitry A. Kazakov wrote: > > Niklas: >>>>> What I have sometimes found annoying is that operations on arrays of a >>>>> parent type cannot easily be applied to arrays of a derived type. >>>>> For example: >>>>> >>>>> type Parent is (A, B, C); >>>>> type Parent_Arr is array (Positive range <>) of Parent; >>>>> >>>>> procedure Print (Item : in Parent_Arr) >>>>> ... >>>>> end Print; >>>>> >>>>> type Child is new Parent; >>>>> type Child_Arr is array (Positive range <>) of Child; > > Dmitry: >>>> If arrays had classes you could inherit the Parent's interface which would >>>> bring Print with it. > > Niklas: >>> It is not clear to me how that would work, in detail. Either one would >>> have to override all the operations for Child_Arr, to substitude Parent >>> with Child, or there would have to be some implicit rules for such >>> substitutions, which would in effect establish the same implicit >>> relationship between Child_Arr and Parent_Arr as I feel already exists. > > Dmitry: >> Yes. Either operations are implemented anew or else they are generated per >> composition of a conversion provided by the programmer with the operation >> of Parent. > > So in the Child/Parent example, how would you "generate" the Print > operation for Child_Arr? Yes. Don't Child_Arr have Print? Are Child_Arr and Parent_Arr same types? The rest follows. > How much more text would that need than the > current work-around, which is: > > procedure Print (Item : in Child_Arr) > is > Parents : Parent_Arr(Item'Range); > begin > for P in Parents'Range loop > Parents(P) := Parent (Item(P)); > end loop; > Print (Parents); > end Print; None assuming the case that Print of Child_Arr to be implemented per composition: procedure Print (Item : Child_Arr) = Print (To_Parent_Array (Item)) I don't have syntax for that, sorry. > (This work-around becomes longer for operations with "in out" parameters.) No. in out operations are composed with two conversions. > Niklas: >>>>> The operation Print on Parent_Arr is not inherited by Child_Arr, > > Dmitry: >>>> Why should it? Child_Arr is unrelated to Parent. > > Niklas: >>> It is just a feeling, and sometimes a practical need. Surely Child_Arr >>> is in some sense related to Parent_Arr, since Child is related to >>> Parent, and the same type construction (array) is used in both? > > Dmitry: >> type A is range 1..100; >> type B is range 1..100; >> >> How do you feel them, same, different? > > Types A and B are different, but both are related to (derived from) > their (unnamed) 'Base types, and probably A'Base is the same as B'Base, > in which case both A and B inherit all operations of that type. Relation must be material, observable. The only way to observe types per operations of these types. The way types were implemented is irrelevant. > I don't think this example is similar to the Child/Parent example. But you are using same logic inventing a relationship of two types from the structure/construction. > Niklas: >>> If a Child is-a Parent, in the sense that primitive operations for >>> Parents are also available (inherited) for Children, why are not >>> operations on collections of Parents available for collections of >>> Children? A collection (array) of Children is-a collection of Parents. > > Dmitry: >> This relationship must be stated explicitly, e.g. Child implements the >> interface of Parent = Child and Parent are in the same class with the >> operations so and so defined. > > "Must" is your opinion. I can disagree. If you favor structural equivalence and inference. > Dmitry: >>>> Somewhere in its >>>> declaration Child_Arr must say "new Parent" or "and Parent." Such type >>>> relationships must be manifested, not implied. > > Niklas: >>> I'm not sure that making the relation manifest in that way is important. > > Dmitry: >> How otherwise you could tell if Child could be used with Print? > > (I assume you mean whether Child_Arr could be used with Print.) The > answer is: by making it a general language rule that "array of > derived-type" inherits operations from "array of parent-type" when the > index types match. This is structural equivalence. The rule you propose actually is: A composite type (e.g. array) is a subtype (=inherits operation, substitutable) of another other composite type when: 1. Their structures match (e.g. array index match, number of components is same etc) 2. Structures of individual components match (e.g. the corresponding component is a subtype/derived type) This is not Ada, or, maybe, was not Ada prior to anonymous access types and procedural access types. > Dmitry: >> Child must >> be in the class of types having Print. Manifested typing requires this >> declared. It is a contract model. > > Contracts (even in real law, I believe) can be implied, and can contain > implied requirements defined by general rules or laws. Whether they > should be manifest (explicitly written out) is a trade-off. Even implied contracts are written somewhere, e.g. in the RM. > In this case, one should consider the possible harm, such as > ambiguities, coding errors, unreadability, etc. that the implicit > inheritance of (in this example) Print from Parent_Arr to Child_Arr > could cause, weigh it against the benefits, and then decide, based on > one's goals for the language. You consider the harm to be larger than > the benefit; I'm not sure yet. One argument against inference is complexity of use, one must keep too much implied things in the head. (It makes the compiler more complex as well) Another argument is inflexibility. The implied contracts are imposed on both sides against their will. You cannot change the RM, when the implied contract is not the one you wanted to have. Then true type equivalence is undecidable. It works for false negatives too, you cannot have equivalent things which cannot be inferred. Furthermore, it is very fragile, because types equivalence would depend on the operations visible in the given context. The key advantage of tagged types is that they freeze the interface. You always know which primitive operations are in effect. For non-tagged types it becomes a swamp. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de