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,6b85f5fd782a1527 X-Google-Attributes: gid103376,public From: adam@irvine.com Subject: Re: How to Use Abstract Data Types Date: 1998/05/04 Message-ID: <6ilt69$j0g$1@nnrp1.dejanews.com> X-Deja-AN: 350297436 X-Http-User-Agent: Mozilla/3.0 (X11; I; Linux 2.0.18 i586) Organization: Deja News - The Leader in Internet Discussion X-Article-Creation-Date: Tue May 05 02:23:05 1998 GMT Newsgroups: comp.lang.ada Date: 1998-05-04T00:00:00+00:00 List-Id: Matthew Heaney wrote: > What's wrong with the iterator-as-type technique? > > package Libraries is > > type Root_Library is abstract tagged null record; > ... > type Library_Iterator (Library : access Root_Library'Class) is limited > private; > > function Is_Done (Iterator : Library_Iterator) return Boolean; > > function Get_Book (Iterator : Library_Iterator) return Book'Class; > > procedure Advance (Iterator : in out Library_Iterator); > ... > end; > > declare > Library : aliased My_Library; > Iterator : Library_Iterator (Library'Access); > begin > ... > while not Is_Done (Iterator) loop > ... Get_Book (Iterator) ... > Advance (Iterator); > end loop; > ... > end; I'm confused about how this should work. As I noted in my response to Robert Eachus, the purpose of setting things up as abstract types was so that I could define new concrete types that represent different implementation of the library. I might have a package Amazon_Library_Package that treats the set of books in amazon.com as a library, and another package that uses a file of books set up as a B-tree, etc. Given this, it seems to me that the Library_Iterator type would also be abstract, since each of the packages that defines concrete types would keep different information in its iterator, depending on what type of implementation it's using. In any case, I don't see how this type could be made "private", since the Libraries package, as declared above, wouldn't have any idea what data is supposed to go into it. When I tried making the Library_Iterator type abstract, I got nowhere, since I wasn't able to define a type extension. I tried this (note: I used shorter names than yours): type Iterator (Lib : access Library'class) is abstract tagged limited null record; and later, in another package: type Test_Library is new Library_Package.Library with private; type Test_Book is new Library_Package.Book with private; type Test_Iterator (Lib : access Test_Library) is new Library_Package.Iterator with private; But I couldn't figure out how to declare Test_Iterator. GNAT gave me "unconstrained type not allowed in this context." Anyway, I'm listing my entire test program below. Hopefully, it should be easy to see what I'm trying to accomplish; maybe you or someone else can figure out how I can do it correctly. -- thanks, Adam =============================================================================== package Library_Package is type Library is abstract tagged null record; type Book is abstract tagged null record; type Iterator (Lib : access Library'class) is abstract tagged limited null record; function The_Library return Library is abstract; function Title (Bk : Book) return string is abstract; procedure Scan_For_Substring (Iter : in out Iterator; Substr : in string) is abstract; function Is_Done (Iter : Iterator) return boolean is abstract; function Get_Book (Iter : Iterator) return Book'class is abstract; procedure Advance (Iter : in out Iterator) is abstract; end Library_Package; with Library_Package; package Test_Library_Package is type Test_Library is new Library_Package.Library with private; type Test_Book is new Library_Package.Book with private; type Test_Library_Acc is access all Test_Library; type Test_Iterator (Lib : access Test_Library) is new Library_Package.Iterator with private; -- ???????????????? function The_Library return Test_Library; function Title (Bk : Test_Book) return string; procedure Scan_For_Substring (Iter : in out Test_Iterator; Substr : in string); function Is_Done (Iter : Test_Iterator) return boolean; function Get_Book (Iter : Test_Iterator) return Test_Book; procedure Advance (Iter : in out Test_Iterator); private type String_P is access string; type Book_Info is record Title : String_P; end record; type Book_Array is array (Natural range <>) of Book_Info; type Test_Library is new Library_Package.Library with null record; type Test_Book is new Library_Package.Book with record Info : Book_Info; end record; type Test_Iterator (Lib : access Library'class) is new Library_Package.Iterator with record Search_String : String_P; Index : Natural; end record; end Test_Library_Package; with Ada.Strings.Fixed; package body Test_Library_Package is My_Library : constant Book_Array := ( (Title => new string' ("A Time To Kill")), (Title => new string' ("The Firm")), (Title => new string' ("The Pelican Brief")), (Title => new string' ("The Client")), (Title => new string' ("The Rainmaker")), (Title => new string' ("The Runaway Jury")) ); function The_Library return Test_Library is begin return ((null record) with null record); end The_Library; function Title (Bk : Test_Book) return string is begin return Bk.Info.Title.all; end Title; procedure Search (Iter : in out Test_Iterator) is begin while Iter.Index <= My_Library'last loop exit when Ada.Strings.Fixed.Index (My_Library (Iter.Index).Title.all, Iter.Search_String.all) /= 0; Iter.Index := Iter.Index + 1; end loop; end Search; procedure Scan_For_Substring (Iter : in out Test_Iterator; Substr : in string) is begin Iter.Search_String := new string' (Substr); Iter.Index := My_Library'first; Search (Iter); end Scan_For_Substring; function Is_Done (Iter : Test_Iterator) return boolean is begin return (Iter.Index > My_Library'last); end Is_Done; function Get_Book (Iter : Test_Iterator) return Test_Book is begin return My_Library (Iter.Index); end Get_Book; procedure Advance (Iter : in out Test_Iterator) is begin Iter.Index := Iter.Index + 1; Search (Iter); end Advance; end Test_Library_Package; with Library_Package; package List_Package is procedure List_Books (Lib : in out Library_Package.Library'class; Substr : in string); end List_Package; with Text_IO; package body List_Package is procedure List_Books (Lib : in out Library_Package.Library'class; Substr : in string) is Iter : Library_Package.Iterator (Lib'access); begin Library_Package.Scan_For_Substring (Iter, Substr); while not Library_Package.Is_Done (Iter) loop declare Bk : Library_Package.Book'class := Library_Package.Get_Book (Iter); begin Text_IO.Put_Line (Library_Package.Title (Bk)); end; Library_Package.Advance (Iter); end loop; end List_Books; end List_Package; with Test_Library_Package; with List_Package; procedure Libtest2 is The_Lib : Test_Library_Package.Test_Library; begin The_Lib := Test_Library_Package.The_Library; List_Package.List_Books (The_Lib, "m"); end Libtest2; -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/ Now offering spam-free web-based newsreading