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,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED!not-for-mail From: Victor Porton Newsgroups: comp.lang.ada Subject: Re: Type invariants and private extensions? Date: Sat, 16 Sep 2017 17:22:42 +0300 Organization: Aioe.org NNTP Server Message-ID: References: <364ff8e0-c7dd-4980-b19f-5d438edd8353@googlegroups.com> <7df81b3c-1fde-4395-8b9b-1a945820a7f7@googlegroups.com> <4565e696-3294-4c27-a761-d18eccb1e1e1@googlegroups.com> NNTP-Posting-Host: mSpCuyqj6nbu/SqiZraDSQ.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Complaints-To: abuse@aioe.org User-Agent: KNode/4.14.10 X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:48147 Date: 2017-09-16T17:22:42+03:00 List-Id: Jere wrote: > On Thursday, September 14, 2017 at 9:52:58 AM UTC-4, Victor Porton wrote: >> Jere wrote: >> >> > On Tuesday, September 12, 2017 at 6:59:17 PM UTC-4, Victor Porton >> > wrote: >> >> Shark8 wrote: >> >> >> >> > On Tuesday, September 12, 2017 at 2:09:08 PM UTC-6, Victor Porton >> >> > wrote: >> >> >> Jeffrey R. Carter wrote: >> >> >> >> >> >> > >> >> >> > "I want to" is not the same as "there is no way to solve the >> >> >> > problem in current Ada". Ada has a feature that provides exactly >> >> >> > what you need. It's called a variant record. >> >> >> >> >> >> It is a tagged type. AFAIK, a type cannot be both a variant record >> >> >> and tagged. >> >> > >> >> > You certainly can: >> >> > >> >> > Type Type_Enumeration is ( TInteger, TReal, TBoolean, Nothing ); >> >> > >> >> > Type Example( Item_Type : Type_Enumeration ) is tagged record >> >> > case Item_Type is >> >> > when TInteger => I : Integer; >> >> > when TReal => R : Float range Float'Range; >> >> > when TBoolean => B : Boolean; >> >> > when Nothing => Null; >> >> > end case; >> >> > end record; >> >> > >> >> >> Moreover, the object in consideration is a wrapper over a certain C >> >> >> API. It surely cannot be described in variant record terms. >> >> > >> >> > Sure it can; there's a reason that there's a separation between >> >> > specification and body, part of which is so you can hide something >> >> > like an interface to C and present something sensible to your >> >> > program/clients. >> >> >> >> Thanks. >> >> >> >> But this seems not to solve my problem: >> >> >> >> The base type for Example cannot be defined as a discriminated type >> >> for certain Type_Enumeration, because it is possible that when >> >> creating the object it may be yet unknown what the value of the >> >> discriminant should have (my main problem is to invent somethings if >> >> this value is known at object creation, but we must support the >> >> unknown case too). AFAIK, it is not possible to change the >> >> discriminant later. >> >> >> > >> > I may be misunderstanding what you are looking for, but you can >> > make discriminant types unconstrained to let you choose the type >> > at run time: >> > >> > Type Type_Enumeration is ( TInteger, TReal, TBoolean, Nothing ); >> > >> > Type Example( Item_Type : Type_Enumeration := Nothing) is tagged >> > record >> > case Item_Type is >> > when TInteger => I : Integer; >> > when TReal => R : Float range Float'Range; >> > when TBoolean => B : Boolean; >> > when Nothing => Null; >> > end case; >> > end record; >> > >> > Then all you have to do is declare an object with no >> > specified discriminant: >> > >> > Some_Object : Example; --notice no discriminant >> > >> > In Ada, when you do this, you are able to assign new versions >> > of the type (with different discriminants: >> > >> > Some_Integer : Example := (Item_Type => TInteger, I => 100); >> > Some_Float : Example := (Item_Type => TFloat, F => 20.2); >> > >> > Some_Object := Some_Integer; >> > Some_Object := Some_Float; >> > >> > That's just a play example, you can handle building them however >> > you want at run time. >> >> It does not suffice for me, because at the point of actual object >> creation, the discriminant value may be yet unknown. Sometimes, I need >> first create the object and LATER (when the object was already created >> and I did some operations with it) assign it the type. >> >> -- >> Victor Porton - http://portonvictor.org > > But that is what this does. You declare your object: > > Some_Object : Example; --notice no discriminant > > Here no discriminant is provided, so it is unconstrained. > > Sometime later (a minute from now, a 100 days from now, etc.) you > get some user input that tells you what type you want (we'll > say an integer for example, but any type you have defined can be > used), you can then simply do: > > declare > Some_Integer : Example := (Item_Type => TInteger, I => User_Input); > begin > Some_Object := Some_Integer; > end; It is not what I need: If we use discriminants your way, I need to create some fields of the object before assignment of the discriminant. This is not possible in Ada: I can assign to object fields only after the discriminant is known. > -- You might even be able to simply do it without a declare block: > -- Some_Object := (Item_Type => TInteger, I => User_Input); > -- I just haven't tried that out. > > and now you have a runtime selected version. You can replace that > Some_Integer with Some_Real or any other version you want. You > don't have to know the type at compile time because the type > Example is unconstrained. > > You can have a discriminated type that is unconstrained so you can > change it freely at runtime. Since the default value of the > discriminant is "Nothing", it handles the object while we are > waiting for input and are basically in an unknown state. You > can rename Nothing to Unknown if it helps for readability. I already pointed that Example(TBoolean) is incompatible with Example(Nothing) (we can't assign a Example(TBoolean) object to an Example(Nothing) variable). That's not acceptable, too. > Does that sound better? -- Victor Porton - http://portonvictor.org