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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6b85f5fd782a1527 X-Google-Attributes: gid103376,public From: matthew_heaney@acm.org (Matthew Heaney) Subject: Re: How to Use Abstract Data Types Date: 1998/05/05 Message-ID: #1/1 X-Deja-AN: 350636120 Content-Transfer-Encoding: 8bit References: <6hm556$95u$1@nnrp1.dejanews.com> <354F5C4D.DFF8286E@gsfc.nasa.gov> Content-Type: text/plain; charset=ISO-8859-1 Organization: Network Intensive Mime-Version: 1.0 Newsgroups: comp.lang.ada Date: 1998-05-05T00:00:00+00:00 List-Id: In article <354F5C4D.DFF8286E@gsfc.nasa.gov>, Stephen Leake wrote: (start of quote) I like this technique, too, but one problem I have with it is it assumes read-write access to the Library. Suppose I want to implement Find: function Find (Title : in String; Library : in My_Library) return Book'class is Iterator : Library_Iterator (Library'access); -- illegal begin ... end Find; Since the Library parameter is "in", you cannot use it as the access discriminant. (end of quote) If you're using GNAT, then you can use the Unrestricted_Access attribute, ie Iter : Lib_Iter (Lib'Unrestricted_Access); begin ... This gives you the ability to make state changes behind the scenes (or, here, supply an in param as an actual discriminant), even though the object is publically read-only. (In Meyer's terminology, you change the "concrete" state without changing the "abstract" state.) C++ programmers take this ability for granted, because you can "cast away const." It's a bummer you can't do that portably in Ada 95. Oh, well. Maybe some programmer will write another article in JOOP explaining that we need to "extend the syntax" of Ada 95... (start of quote) The only way around this (that I have found) is to restructure Find to be a procedure, with Library "in out" and the Book result as an "out" parameter. (end of quote) Not necessarily. You can keep the functional form by making library an access parameter: fuction Find (Title : String; Lib : access My_Lib) return Book'Class is Iter : Lib_Iter (Lib); begin ... Now the code is completely portable too. Yes, it seems like a bummer that I should have to make a param in out or access, even though it's read-only. But this is just a "feature" of the language. (start of quote) With the generic package iterator: generic type Some_Library is new Library with private; This_Library: in Some_Library; package Iterator is function More return Boolean; function Next return Book'Class; end Iterator; "This_Library" is now read-only. (end of quote) I haven't played around with generic packages as iterators - though I have imported iterators as a generic formal parameter. See my follow-up post that answers Adam's questions. (start of quote) Is there a good way to get read-only access with Iterator_Type? (end of quote) Non-portable way (GNAT only): yes, using O'Unrestricted_Access. Portable way: no. You have to either pass the param as an access param (works for any kind of type, even non-tagged types) or as in out (works for tagged types only).