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=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!feeder.eternal-september.org!news.glorb.com!peer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!post01.iad.highwinds-media.com!fx17.iad.POSTED!not-for-mail From: Brad Moore User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: How to use read-only variables? References: In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Message-ID: NNTP-Posting-Host: 68.145.219.148 X-Complaints-To: internet.abuse@sjrb.ca X-Trace: 1420338848 68.145.219.148 (Sun, 04 Jan 2015 02:34:08 UTC) NNTP-Posting-Date: Sun, 04 Jan 2015 02:34:08 UTC Date: Sat, 03 Jan 2015 19:33:57 -0700 X-Received-Bytes: 4434 X-Received-Body-CRC: 4241150584 Xref: news.eternal-september.org comp.lang.ada:24336 Date: 2015-01-03T19:33:57-07:00 List-Id: On 15-01-03 05:58 PM, hreba wrote: > My Ada book says that 'access const' types serve for readonly > variables but I am not sure whether I grasped the idea. The idea is that whatever that the access const designates (points to), it cannot be modified via that access. > > I want a readonly variable 'n' as component of a record 'R'. The > variable which is accessed by 'n', let's call it 'nv' must be hidden, > otherwise the client could change it. For what you are trying to accomplish, it seems an awkward roundabout way to do it. The troubles you are having with access types might suggest that there is a better way to do what you want to do. If you only want a read only integer component of record 'R', consider making it a non-mutable discriminant. eg. type R (N : Integer) is null record; Then any declaration of type R will have N specified and the client cannot change it. There is no need for it to be hidden. A : R (N => 3); -- The N value of A cannot be modified If you really want it to be hidden, then you can declare the type with unknown discriminants, but then you need an initialization function to create objects of that type, because you cannot declare unconstrained objects. Clients would not be able to refer to the N value directly, but you create provide a function that returns the N value as part of the abstraction. eg, package P is type R (<>) is private; function Create (N : Integer) return R; function Get_N (Item : R) return Integer; private type R (N : Integer) is null record; function Create (N : Integer) return R is (N => N); function Get_N (Item : R) return Integer is (Item.N); end P; If you want it to be read only from the client perspective but modifiable locally, use a private type. package P is type R is private; function Create (N : Integer) return R; function Get_N (Item : R) return Integer; private type R2 is record N : Integer; end record; function Create (N : Integer) return R is (N => N); function Get_N (Item : R) return Integer is (Item.N); end P; > > Consequently 'R' must be extensible, that is tagged. No need for tagged types in the suggestions above. It makes no sense > to use the base class alone (without something for 'n' to point to), > so it must be abstract. As the pointer-target relation wouldn't be > conserved in a simple assignment, the record must be limited. No need for abstract or limited in the above either, and no need for access types, or dealing with the error messages in the original post. Brad This > leads to > > type R is abstract tagged limited record > n: access constant Integer; > end record; > > type Rv is new R with private; > > private > > type Rv is new R with record > nv: aliased Integer; > end record; > > The value of 'n' would be defined in an initialization procedure: > > procedure Init (rec: in out Rv) is > begin > rec.n:= rec.nv'Access; > end Init; > > This however gives me an error message: > > non-local pointer cannot point to local object > > Now I am really confused: > > - Are readonly variables really handled this way, typically? > - How can rec.nv be local and rec.n not? > - How would you write the correct initialization procedure? > > All this seems pretty complicated to somebody used to Oberon, where > all this would be simply written as > > TYPE > R* = RECORD > n-: INTEGER; > END; >