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: jsa@alexandria (Jon S Anthony) Subject: Re: Allocating "initialized" limited types... Date: 1996/09/02 Message-ID: X-Deja-AN: 177903542 sender: news@organon.com (news) references: organization: Organon Motives, Inc. newsgroups: comp.lang.ada Date: 1996-09-02T00:00:00+00:00 List-Id: In article bobduff@world.std.com (Robert A Duff) writes: > In article , > Jon S Anthony wrote: > >What was the reasoning behind the 4.8(7) definition that an initialized > >allocator boils down to an assignment? Any reason why this could not have > >been defined as the creation of an instance with the fields as given by > >the qualified expression? > > Well, it *is* a copy, and the whole point of limited types is to prevent > copying. I don't see any difference between assignment and just copying > all the fields over -- that's what assignment *does*. Well, it *is* a copy if that's how you define it. You don't have to so define it in the user model. And sure, copying all the field over is basically assignment anyway. > For example, suppose there is a limited private type implemented as an > access type. The designer of that abstraction wanted to prevent having > two such pointers pointing to the same thing, and so made it limited. > Now, a client says: > > X: The_Limited_Type; > type T is access The_Limited_Type; > Y: Y := new The_Limited_Type'(X); -- Illegal. > > If this were legal, the client would have succeeded in making a copy of > X, which is exactly what "limited" is supposed to prevent. Yes, yes, of course. That's actually why I'm using it for crying out loud. But in the _body_ of where the thing is defined this is just irrelevant as you can copy the fields of X one at time and make your copy any way. This too, is part of the point. 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...). [more obvious stuff deleted...] > I don't see why allocators are special -- a copy is a copy. 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. > Ada 95 went to some trouble to patch some holes in Ada 83 where one > could make copies of limited types, by the way. Yes, and that was a "good thing". > > type C is new T with private; -- Extends with new fields... > >... > > A_List : Car_Cdr_List_Where_Car_Is_T_Ref; > > Obj_Ref : T_Ref; > > > > loop > > ... > >(1) Obj_Ref := new C'(....); -- ILLEGAL, assignment to limited type! > > It's not clear to me what you plan to put in the "....", since T and C > are both private. Not to the _BODY_. So, it is TRIVIAL to put _NON COPY THINGS_ in the '(...) Actually, this is probably more to the point. If you could have had public limited views of _tagged_ types with their private views being _NON_limited, this would solve the problem nicely. So, I guess the question should have been why was this disallowed. Actually, I seem to recall a reason for this, but can't recall what it was (seemed to make sense at the time...) > >(2) A_List := Obj_Ref + A_List; > > ... > > end loop > > > >(*) Changing (1) to > > > > Obj_Ref := new C; > > Obj_Ref.New_Field1 := ... -- ILLEGAL, No such field in this view! > > You can say C(Obj_Ref.all).New_Field1 := ... > > Not exactly pretty, but it works. Yes, but I think my hack is nicer than this one... > 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. So, this one didn't work for me in the case at hand. But this _is_ a nice way to go if it fits. > >Doesn't help and is much more prone to errors (forget one of those fields???> > Maybe you're really asking why limited types don't allow aggregates? > The "don't forget fields" feature is a property of aggregates, not > allocators. It's not clear how one could deal with access discrims in > an aggregate. No, I really think what I was after is the above bit about limited public and non limited private views of tagged types. To me, not allowing an aggregate is obvious: it is an assignment to the object (not to its separate fields!) and thus illegal for limited types. > Maybe you could come up with some rules that allow aggregates in some > cases, but only in initial values. Yes, that would work too. But you're correct that is a kind of special case hack. Still... > Note that "X: T := expression;" is analogous to "new > T'(expression);" -- both are initializers. The idea would be, I > suppose, that the aggregate is built "in place", so there's no copy. 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. > You could also allow function_calls, where the function returns a > local, if you're willing to have that local live outside the > function (i.e. the local "becomes" the new object being > initialized). I think Henry Baker once published a paper along > those lines, but I don't have a reference (sorry). I'll take a look at his jumbo web site for his papers... > between access types. There are many other cases. The problem is that > you normally want type-equivalence-by-structure for access types, > 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! /Jon -- Jon Anthony Organon Motives, Inc. 1 Williston Road, Suite 4 Belmont, MA 02178 617.484.3383 jsa@organon.com