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 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!mx05.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Is this expected behavior or not Date: Fri, 5 Apr 2013 11:57:34 +0200 Organization: cbb software GmbH Message-ID: <1bj564vat3q1j$.1s4d00rlzx4ux$.dlg@40tude.net> References: <2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net> <1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net> <1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net> <3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net> <1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net> <1fmcdkj58brky.bjedt0pr39cd$.dlg@40tude.net> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: FbOMkhMtVLVmu7IwBnt1tw.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: 40tude_Dialog/2.0.15.1 X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:14867 Date: 2013-04-05T11:57:34+02:00 List-Id: On Thu, 4 Apr 2013 15:31:23 -0500, Randy Brukardt wrote: > "Dmitry A. Kazakov" wrote in message > news:1fmcdkj58brky.bjedt0pr39cd$.dlg@40tude.net... >> On Wed, 3 Apr 2013 19:04:24 -0500, Randy Brukardt wrote: >> >>> "Dmitry A. Kazakov" wrote in message >>> news:1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net... >> >>>> If you have more than one controlled argument/result of the same type, >>>> that makes it a multi-method. The natural consequence of this is that all >>>> possible combinations of types from the hierarchy are specific bodies to >>>> inherit/override. In Ada 95 only the bodies when all types are same can >>>> be overridden. Statically the compiler prevents calls to mixed types bodies, >>>> but they nevertheless exist and can be reached through dispatch. In that >>>> case it works as if the body were "rase Constraint_Error." This hack >>>> won't work for &, =, <, <= etc. Those require almost all combinations to work. >>> >>> I see where you are coming from, but I don't agree with any of it on a >>> fundamental level: mixing types in operations is virtually always an >>> error (either a real mistake or a design error). >> >> How is it an error to compare String and Wide_String? > > The same way it is an error to compare a float and an integer. It is not same. R and Z are different mathematical constructs. Unicode strings, all of them, are semantically exactly same except for encoding [representation] and constraints put on the code point set. > You could > make a rule with somewhat sensible results, but it's a bad idea because it > hides more errors than it simplifies correct code. If that were so, you should not have them in the same hierarchy. You want to have one class in order to share operations like Put_Line. These operations are far more questionable than comparison. If you challenge comparison, you should not do Put_Line either. You design decisions are motivated by compiler implementation issues not by the actual properties of strings. >>> I don't believe that these use cases are at all common. I don't recall >>> any such cases in Claw, for example, which uses Ada 95 inheritance >>> extensively. >> >> That is because GUI does not require dyadic operations at all. There are >> few cases for MD though. E.g. >> >> procedure Render (Surface : in out Device_Type; Shape : Geometric_Type); >> >> And of course: >> >> procedure Set_Text (Control : Edit_Box; Text : Root_String_Type); > > This is clearly class-wide: > > procedure Set_Text (Control : Edit_Box; Text : Root_String_Type'Class); > > The implementation would use the constructor for Text to create the value, > so it's straightforward to implement. (The Edit_Box has to have some > particular representation for text, even if the result does not.) Now this: function Get_Text (Control : Edit_Box) return Root_String_Type; >>>> The only pattern that sometimes works is recursive cascaded dispatch. >>>> That is when you make one argument controlled and another class-wide. >>> >>> Gosh, that's what I was talking from the beginning. >> >> It works only with dyadic operations, procedures or else functions >> returning an alien type. > > Which is 95% of the cases that you would want. No more than 20-30% actually. >>>> I used it for "=" and "<" multi-method operations of the target type >>>> hierarchy of >>>> smart pointers. I needed this to be able to have ordered collections of >>>> smart pointers to such objects when pointers are ordered by the objects >>>> they point to. It is extremely tedious, involves recursive calls and >>>> explicit tag comparisons for ancestry. It won't work with for operations >>>> like &, which has two arguments and the result. >>> >>> You don't want mixed operations in cases like "&", ever. >> >> Non-starter for strings. > > Mixed operations are almost always a non-starter for any type. Mixed operations are a must for all algebraic types and all string types. Ada 83 had it mixed from the start, e.g. Universal_Integer vs. Integer. Ada 95 added mixed operations for access types. Without mixed operations, hierarchies of scalar type, strings, access types were useless. >> It need not to be understood. The programmer will be asked to override >> operation or else to make type abstract, just as Ada 95 did. > > You have to avoid this sort of thing, You cannot avoid it, because there is no way the compiler could define it semantically correct. > the Ada 95 effects make it absolutely > necessary to avoid functions returning a controlled type, else creating > extensions is so hard that no one will do it. I don't know where you get that idea. I never had any problem with abstract factories. Actual problem is fighting senseless limitations imposed by the language, which makes design very hard as you never know if the derived type would be possible to construct. Limited aggregates/functions, broken initialization/finalization, leaking separation of specification and implementation, missing initialization/finalization of class-wides etc. That makes it difficult. >> Not at all, the compiler is free to choose, so it must. [I don't consider >> schizophrenic compilers choosing one way and doing in another. That does >> not work with any model.] > > It doesn't work for portability reasons for some compilers to call Adjust > during the evaluation of parameters and other compilers to not call Adjust. When the type neither specified as either by-reference nor as by-value, it shall be exactly this way. I don't understand why this is relevant. > It would make performance wildly variable and possibly cause bugs (if the > program unintentionally depended on one or the other. Yes, the language permits compilers implemented poorly, and? >>> You'd have to forcibly specify one >>> or the other for all types, which is certain to be incompatible with >>> existing implementations. >> >> The compiler vendor simply follows the choice he made before. > > Thus making most Ada code non-portable. No more than they already are. The program that exploits certain type of parameter passing for a type which is not specified as either by value or by reference is erroneous. End of story. >>> It strikes me that the model of stripping tags means that type conversion >>> of an object to a class-wide type would effectively change the tag (if the >>> routine was inherited or called by a conversion of an operand). >> >> Yes, re-dispatch is a broken thing. Don't do it, because it is ambiguous >> in general case when objects do not have an identity. By-copy scalar types >> are such things. There is nothing which could distinguish Integer 13 from >> Long_Integer 13 except the context. Once you dispatched that information >> is lost. There is no way back. >> >>> That would >>> mean that the behavior of such a conversion would be very different for >>> an untagged type and for a tagged type. >> >> Not different. It is just so that tagged types per design have type >> identity. Other types simply don't have it. > > Objects of limited types are always assumed to have an identity; No. E.g. task and protected types lack type identity. Only tagged types have type identity. Note that type identity /= object identity (e.g. machine address where the object resides). >>>> No change either. If a by-copy object passed by value has a controlled >>>> component that component is copied-in and out using Adjust and >>>> Finalization. >>> >>> That's the problem. If that is done in existing code, you have an >>> incompatibility (because the same code does something different now). >> >> Why? If that type is by-copy then this is how it must work already. If it >> is by-reference then nothing changes either. > > Because currently, you don't call Adjust/Finalize for a type conversion. And > it would have to be specified whether a type is by-copy or by-reference (it > could not be left to the compiler with these rules, as I previously > mentioned) -- that means compilers would have to change in some cases. No, it will stay exactly as it is now. Type conversion is irrelevant. >>> A more general model that is many times more complex than the existing >>> model. What exactly is being simplified? >> >> You will have all strings in one hierarchy. All characters in another. All >> integer types in third. Tagged types described using a footnote. > > That's already true, you just don't have inheritance of operations for these > hierarchies. So exactly what you are simplifying but introducing this whole > new notion of type cloning, this new notion of when you must override > routines, and so on?? I don't introduce anything Ada 83 or 95 do not have already. I want to lift meaningless language limitations which lead to silly design decisions like inability to concatenate or compare two strings. >> You want to derive each string type straight from Root_String. > > Yes, or from related ones. There is no significant value to doing anything > else - as you point out, if you can inherit the operations, the > representations have to be compatible. So there is nothing useful you can do > with multiple levels. Encoding! -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de