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,5606d8433901738c X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Allocating "initialized" limited types... Date: 1996/09/03 Message-ID: X-Deja-AN: 178206742 references: organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-09-03T00:00:00+00:00 List-Id: In article , Jon S Anthony wrote: >Hmmm, actually there is another point poking through here: What I had >in mind was an aggregate where all the fields are specified (as non >copies) - not the sort of case where you use an _object_ of the type >for the aggregate. Actually, I didn't even know you could do this - >thought that was a simple qualified expression (then again, I guess >that's what an aggregate is...). A qualified expression can contain any sort of expression inside the parens, not just an aggregate. The syntax special-cases aggregates, just so you can leave out one pair of parens -- you can write T'(a,b,c) instead of T'((a,b,c)). And an initialized allocator contains a qualified expression. >Fine. If that is the reasoning that went into it. My claim is that >in the user model it does not have to be a copy. I suspect you're right -- you *could* define a language feature that made initialization work the way you want. >> Another useful trick is to make all the record fields into discriminants >> (possibly of access type). Then you can initialize them using a >> discriminant constraint, which does the full coverage check you want. > >Yes, I've done this one too - it is _very_ useful, but not in those >cases where the discriminants are to be hidden. I don't understand what you mean, here. Ada 95 added the "unknown discrims" feature so you can hide discrims. E.g.: package P is type T(<>) is ... private type T(Length, Width: Integer) is ... end P; >Yup, that is precisely the idea that I had in mind by the notion that >you would not have to define an initialized allocator as a copying >operation. You have nailed down what I really had in mind. The >reason allocators _seem_ special here, is that there is no object in >the _user model_ that is being assigned! > >X : T := expression; -- Clearly an assignment IN THE USER MODEL to a T object > >X : T_Ref := new T'(...); -- NOT an assignment to a T object > -- IN THE USER MODEL. In the user model > -- a T_Ref object is being assigned! Sure, > -- in the nefarious innards of the language > -- model this too has an assignment to a T > -- object - as currently defined. Well, hmph. If the user has that model, then the user's model is wrong. The two cases of initialization are entirely analogous. In the second case, the heap object is being explicitly initialized. Look at the rules in the RM for the two cases -- you will see a lot of parallels, and that's intentional. So, I would claim that if the feature you are looking for (a way to initialize limited objects with compile-time checking for missing components) existed, then it should exist for initializing stack objects *and* heap objects. >> whereas Ada always uses (essentially) type-equivalence-by-name. Access >> parameters are helpful, but that only works for parameters. >Not when you are using access to class wide types. That is more or >less the whole point of such things. One named type representing whole >sets of possible structures. Criminey, that's the whole point! I'm not sure what that "not" refers to, or the "such things". You *can* have an access parameter whose designated type is class-wide. I do it all the time, precisely because it doesn't require a bogus type_conversion. Unfortunately, you can't do that for other things, like record components and stand-alone variables. E.g.: type T1 is ... type T1_Ptr is access all T1'Class; type T2 is new T1 with ... type T2_Ptr is access all T2'Class; X: T1_Ptr; Y: T2_Ptr; X := T1_Ptr(Y); -- Grr. I find the above type_conversion to be annoying rubbish, because it can't possibly fail, and it doesn't do anything, and it doesn't tell the reader of the code anything interesting. It's nice that I can pass Y to a parameter of type "access T1'Class", but it's annoying that the same thing doesn't work for things that aren't parameters. That was *my* point. Did I misunderstand *your* point? Perhaps we should have defined access-to-tagged to allow implicit conversions up the hierarchy. It's a bit tricky to get the overload resolution rules right, so they don't cause Beaujolais effects, but I think it's possible. (By the way, we should not have defined the "access all" feature. We should have just made all access types work that way. There's really no *important* reason for the language to have both "access Foo" and "access all Foo". This design mistake was largely my fault -- during the language design, I argued strongly for the "all" feature. I've since changed my mind, since I end up almost always using "all" anyway.) - Bob