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,73cb216d191f0fef X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit X-Received: by 10.180.106.73 with SMTP id gs9mr789168wib.2.1365267377115; Sat, 06 Apr 2013 09:56:17 -0700 (PDT) Path: ex12ni26833wid.1!nntp.google.com!feeder1.cambriumusenet.nl!82.197.223.108.MISMATCH!feeder2.cambriumusenet.nl!feed.tweaknews.nl!85.12.40.131.MISMATCH!xlned.com!feeder3.xlned.com!198.15.118.135.MISMATCH!us.feeder.erje.net!1.eu.reader.erje.net!feeder.erje.net!eu.feeder.erje.net!weretis.net!feeder4.news.weretis.net!rt.uk.eu.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Is this expected behavior or not Date: Wed, 3 Apr 2013 10:54:30 +0200 Organization: cbb software GmbH Message-ID: <1gkxiwepaxvtt$.u3ly33rbwthf.dlg@40tude.net> References: <1raubw1sk48ca$.69rdgczvnnf.dlg@40tude.net> <2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net> <1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net> <1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net> <3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: FbOMkhMtVLVmu7IwBnt1tw.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: 2013-04-03T10:54:30+02:00 List-Id: On Tue, 2 Apr 2013 16:54:01 -0500, Randy Brukardt wrote: > "Dmitry A. Kazakov" wrote in message > news:3gv2jwc95otm.pl2aahsh9ox8.dlg@40tude.net... >> On Mon, 1 Apr 2013 19:40:42 -0500, Randy Brukardt wrote: >> >>> "Dmitry A. Kazakov" wrote in message >>> news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net... >>> .... >>>> The point is that whether you create a totally new string hierarchy or >>>> create one for already existing string types, you will have the issue with >>>> "&" (and any other operation with more than one argument/result of string >>>> type). That is *independent* on whatever Ada did or not before. It is in >>>> the nature of a multi-method, which "&" is. If you want a hierarchy of >>>> strings you *must* face this problem. >>> >>> No you don't. There are no language-defined multi-methods. String & >>> String = String is not a multi-method. >> >> Once String becomes member of a class it is. For the operation "&" there >> exist only two possibilities, Either it is a primitive operation of the >> class and so a multi-method, or else it is declared individually on each >> member of the class in separate packages (somewhere after the freezing >> point). The later variant is so silly that I don't even consider it. > > I agree that latter variant is silly, but the notion that somehow "&" > becomes a multi-method simply because it exists makes no sense. "=" is not a > multi-method in Ada today for tagged types; Assignment should certainly be a multi-method, because in some cases you want to be able to assign one type of the hierarchy to another. Assignment is a bit special case because the target's tag cannot be changed anyway. That reduces the number of use-cases for mixed types. Others could be further reduced using constrained subtypes, but they still exist. As a multi-method use case consider a tagged class with the operations "=" and "<" defined. These must support mixed types almost always. > "&" would work the same way - it > does not take items of different types unless you explicitly convert them. > Maybe you have a different idea of a multimethod than I do?? 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. >>> You, the user, can define such operations, of >>> course, but then you have the deal with the consequences. Generally, it's >>> best if you don't do that. >> >> What is the use of a string type without operations? > > Huh? There are predefined single-type operations. If you want mixed type > operations, you have to define them, It would be a combinatorial explosion of variants and a huge issue with visibility. The language should support this use case, because it is a pattern for all dyadic operations, assignment, comparisons. > but it's usually a bad idea to do so. > You're almost always better off with 'Class operands if you need type > mixing -- for type resolution reasons (not even mentioning runtime issues). That does not solve the problem, you will get Constraint_Error. The only pattern that sometimes works is recursive cascaded dispatch. That is when you make one argument controlled and another class-wide. 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. >>> And there exist plenty of Ada >>> types for which copying is not allowed. >> >> No problem. See above. All primitive operation will be inherited abstract >> if the representation is not inherited and no [user-defined] conversion >> defined (e.g. for a by-reference type). > > That was a bad idea for Ada 95 (there are pretty severe visibility issues > associated with it), and I don't think it can be extended. It was a great Ada 95 idea, because covariant out-operations are unsafe to inherit under type extension. *The compiler shall not make any assumptions* > In any case, that > extends the problem of creating extensions -- it would be so diifficult and > time-consuming that it almost never would be done. It is not an extension, it meant to be the same interface and a completely different representation. Extension is the same interface and extended representation. Anyway, the point is, that the compiler shall inherit a body IF AND ONLY IF it knows that this would be safe to do. That is the following cases: 1. Any operation when the representation is same 2. In-operation when the representation is extension or constraint 3. Out-operation when the representation is generalization (lifted constraint) [Ada does not have this, as an example consider extension of an enumeration type] 4. User-defined conversion defined, programmer's responsibility [Ada does not have this] On top of that come pre- and post-conditions which may in their turn disallow inheritance of the body. >>> The only way to implement those is >>> via some sort of dispatching, and the need poisons the possibility of >>> omitting tags, even for "specific" operations. >> >> I don't understand where you get this. The model is exactly the model of >> tagged types, but without specific objects required to keep the tag. The >> only thing it influences is view conversions between T and T'Class. >> Nothing else is changed. > > When you dispatch to an inherited routine, you directly call that routine > with the operands view converted (which cannot make copies in the general > case). For by-copy types dispatching call will be copy-in / copy-out. The representation of T'Class is tag + value. Tag is stripped, value passed through. For by-reference untagged types dispatching call will pass the reference. The representation of T'Class is tag + pointer. Tag is stripped, reference passed through. >>> That >>> forces the representation to be compatible. You could change that for >>> by-copy types (although that would have run-time compatibility issues for >>> controlled objects), >> >> Controlled objects are tagged, hence no change here. > > A component is an object; I'm talking about untagged objects with controlled > components here. 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. >>> but you can't change that for types that have no copy >>> operation (like tasks and protected objects). So how to do you implement >>> them? Array of task is an untagged type, too, and it certainly should be >>> able to use 'Class. >> >> Sure. T'Class will be a referential object when T is untagged by-reference >> type. It will consist of the type tag and a *pointer* to the specific >> object (not much different from 4.1.5), and from view conversions ether, >> though formally a new object. >> >> When T is by-copy, T'Class is the type tag + a copy of T. > > Wow! And this is supposed to be a *simplification*??? :-) Yes. It is much simpler to view tagged types as a special case [definite representation constraint] of a more general model that encompasses all types. >>>>> It really kills the entire idea. >>>> >>>> No, IF String inherited the representation of Wide_Wide_String, THAT >>>> would kill the idea. >>>> >>>> The whole idea is not to inherit irrelevant representations! >>> >>> I don't see the problem here; if Root_String is an abstract tagged type, >> >> Java interfaces will not work for characters/strings. No need even to try it. > > Java interfaces will not work for anything. No need to even try. :-) And > who's talking about Java, anyway? You want strings hierarchy of one level depth. That won't work. > I'm interested in what we can do with tagged types. Forget the silly > interfaces, or call it an interface if that makes people feel better (that's > what we did with iterators, but it doesn't actually buy you anything). It's > an Ada 95 abstract type. If so, allow to inherit from more than one. Allow to inherit only interface from such a type. You have the problem of "&" at hand. It cannot be solved without the above mechanisms. And multi-method and MI is only a start. The real problem is *full* MD as "&" is defined on String and Character. >> The proper pattern would be: >> >> type Measurement is digits 5 range -1.0E+10 .. 1.0E+10; >> ... >> type Velocity is new Measurement; >> type Acceleration is new Measurement; >> ... > > This is a terrible design pattern because it puts unrelated types together > (and, allows them to be converted to a common ancestor, which almost always > is a bug - especially if we had Measurement'Class). They are related, Acceleration is computed from Velocity and Duration. On top of that come a huge pile of generics (can't rid of them) instantiated with Measurement, e.g. I/O, GUI stuff. In real-life case you can't do that with individual types. You need a class and this is what Measurement is for. >>> Either you have a conversion to the original >>> type, in which case they belong to the same hierarchy. >> >> This is a possible way to implement cloning. This is not the semantics of. >> The semantics is that there is a new set of types, values and operations >> with the properties of the original. Nothing more. > > If they allow conversion (including implicitly to the class-wide root of the > class) and instantiation, they're members of the same hierarchy. The semantics for tagged types (if they were supported) should be creating a new type for each parent type. type T is new Ada,Finalization.Controlled with ...; type Q is new T; X : Q; Y : Ada.Finalization.Controlled'Class := X; -- Type error Z : Ada.Finalization.Controlled'Class := T (X); -- OK Q is not an extension of Ada,Finalization.Controlled. It is of some anonymous type cloned from Ada,Finalization.Controlled: type is new Ada,Finalization.Controlled; -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de