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.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,85d5a13738392342 X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII Path: g2news2.google.com!postnews.google.com!v10g2000yqn.googlegroups.com!not-for-mail From: Simon Belmont Newsgroups: comp.lang.ada Subject: Re: Unknown discriminants with nested records Date: Thu, 16 Jun 2011 18:48:51 -0700 (PDT) Organization: http://groups.google.com Message-ID: <2191e8b5-e827-41e8-b8a0-f02b8a68362c@v10g2000yqn.googlegroups.com> References: <1e197c14-a2ff-4867-85be-fda06a10e37b@a7g2000vby.googlegroups.com> NNTP-Posting-Host: 24.218.138.255 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1308275444 22586 127.0.0.1 (17 Jun 2011 01:50:44 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Fri, 17 Jun 2011 01:50:44 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: v10g2000yqn.googlegroups.com; posting-host=24.218.138.255; posting-account=ShYTIAoAAABytvcS76ZrG9GdaV-nXYKy User-Agent: G2/1.0 X-Google-Web-Client: true X-Google-Header-Order: ARLUEHNKC X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; InfoPath.2),gzip(gfe) Xref: g2news2.google.com comp.lang.ada:20872 Date: 2011-06-16T18:48:51-07:00 List-Id: On Jun 16, 8:39=A0pm, Adam Beneschan wrote: > On Jun 16, 4:53=A0pm, Simon Belmont wrote: > > > > > > > New to ada (2005), and trying to figure out how to create records of > > other records with unknown discriminants, e.g. like this: > > > package Test_Package is > > > =A0 =A0 type Foo_Type (<>) is limited private; =A0-- some record with > > unknown discriminants. > > > =A0 =A0 t1: Foo_Type :=3D MakeAFooType; -- works fine being built by a > > function > > > =A0 =A0 type BarType is > > =A0 =A0 record > > =A0 =A0 =A0B1: Integer; > > =A0 =A0 =A0-- other record elements > > =A0 =A0 =A0B2: FooType :=3D MakeAFooType; =A0-- Error, unconstrained su= btype. > > =A0 =A0 end record; > > > private > > > =A0 =A0 type FooType is limited > > =A0 =A0 record > > =A0 =A0 =A0F1: Integer; > > =A0 =A0 end record; > > > end Test_Package; > > > The (<>) seems to be the defacto way to limit creation to a function, > > yet it seemingly precludes you from using it in a nested record. =A0It > > seems strange that there is the ability to declare a standalone object > > of that type, but trying to nest one within another record throws an > > "unconstrained subtype" error; if it knows the constraints one place, > > why doesn't it know them several lines down? > > To start with, it's helpful to post the actual source you tried. > Clearly this isn't, since you didn't spell Foo_Type consistently, but > the more important problem is that you've stuck the declarations T1 > and BarType in the middle of Test_Package where they don't belong. > You can't declare T1 to be a Foo_Type at that point, because > Foo_Type's definition hasn't been finished. =A0Anyway, I'll assume that > T1 and BarType are actually declared in some other package > Test_Package_2 that with's and uses Test_Package. > > The basic problem is this: When Test_Package_2 is elaborated, and it > elaborates the definition of T1, it will call MakeAFooType at that > point. =A0The discriminants (if any) of the value will then be > determined, so T1's discriminants will then be known. > > But when BarType is elaborated, MakeAFooType isn't called. =A0The use of > MakeAFooType here is a *default* expression. =A0When you later declare > > =A0 =A0B : BarType; > > with no initial expression, MakeAFooType will be called at *that* > point, when B is elaborated. =A0It's also possible to declare B with an > initial expression like > > =A0 =A0B : BarType :=3D (B1 =3D> 1, B2 =3D> Make_A_Different_Kind_Of_Foo)= ; > > so that MakeAFooType wouldn't be called at all. =A0So here, the > constraints of the B2 component won't be what MakeAFooType would > return. > > Hopefully that will answer your question about "why doesn't it know > [the constraints] several lines down". =A0It doesn't know because that > syntax doesn't actually result in a function call. > > The problem here is that since the initial expression on the component > is just a *default* and may not be the actual initial expression for a > B2 component, the compiler thus doesn't know what constraints a B2 > will have. =A0In theory, since it's possible for objects with different > constraints to have different sizes, the compiler thus may not know > how big a BarType will be, and I think that's the technical reason why > this sort of component type is prohibited. =A0(In practice, it might be > possible to make this work, since often the size of a FooType won't > vary; but it might be hard to do without introducing some incompatible > changes in the language. =A0I don't know if any possible language > changes have ever been discussed.) > > As for how to get around this: if it were me, I'd just lose the (<>). > The (<>) was intended to define types with unknown discriminants; > using it to force initialization functions to be used, when you know > there won't really be any discriminants, is using this feature for a > purpose for which it wasn't intended, I think. =A0Someone clever found > that it works for this purpose, but obviously it doesn't work all the > time. =A0Maybe a language feature should be added that allows the user > to define a *definite* type that still isn't allowed to be > uninitialized. =A0Here's a possible way to force all uses of this type > to be initialized: > > package Test_Package is > =A0 =A0 type Foo_Type is limited private; > =A0 =A0 ... etc. etc. > private > =A0 =A0 function Blow_Up return Integer; > =A0 =A0 type Foo_Type is limited > =A0 =A0 =A0 =A0record > =A0 =A0 =A0 =A0 =A0 F1 : Integer :=3D Blow_Up; > =A0 =A0 =A0 =A0end record; > end Test_Package; > > where Blow_Up is defined like: > > =A0 =A0 function Blow_Up return Integer is > =A0 =A0 begin > =A0 =A0 =A0 =A0raise Program_Error with "You forgot to initialize your > Foo_Type"; > =A0 =A0 =A0 =A0return 0; =A0-- never executed > =A0 =A0 end Blow_Up; > > or something along those lines. =A0This won't be caught at compile time > (although some compilers may display a warning that Program_Error will > be raised), but a program that declares a variable that is or contains > an uninitialized Foo_Type will bomb. > > > 4. Can anyone point me to the section in the LRM that specifies this > > either way? > > 3.6(10). =A0This is in the section on array types, but the restriction > on a component's type applies to record type components too. > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- Ada= m- Hide quoted text - > > - Show quoted text - Thank you very much, that was the exact answer I was looking for. I was supposing too much about the operation of the unknown discriminent marker; I figured it was more of a "known-but-I-won't-tell-you-because- you-don't-need-to-know" marker than an actual "unknown", and that the compiler would be able to determine that the record in question didn't, in fact, have any real discriminents. It would certainly be nice if there were some sort of language feature for this, especially considering that, like you said, the entire community makes it standard practice to deliberity misuse an operator. But if it's been 16 years without one, I doubt there it would be high on the priority list (though IMHO these priorities seem skewed; some of the things on the 2012 list seem frivilous compared to more basic things like making sure objects are properly initialized). As for the suggestion, I am loathe to circumvent the compile-time safety (after all, that seems like the whole point of using Ada). My next thought is to simply make it an access type in the record, and then create a new Foo on the heap each time someone uses the hypothetical MakeABar, though I'm not sure using the heap that much is any better... In either case, thank you again for your spot-on explanation.