comp.lang.ada
 help / color / mirror / Atom feed
From: adam@irvine.com
Subject: Re: How to Use Abstract Data Types
Date: 1998/05/04
Date: 1998-05-04T00:00:00+00:00	[thread overview]
Message-ID: <6ilt69$j0g$1@nnrp1.dejanews.com> (raw)


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




             reply	other threads:[~1998-05-04  0:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-05-04  0:00 adam [this message]
1998-05-06  0:00 ` How to Use Abstract Data Types Robert I. Eachus
  -- strict thread matches above, loose matches on Subject: below --
1998-04-30  0:00 adam
1998-05-06  0:00 ` Robert I. Eachus
1998-04-22  0:00 adam
1998-04-23  0:00 ` Jacob Sparre Andersen
1998-04-30  0:00 ` Robert I. Eachus
     [not found]   ` <matthew_heaney-ya023680003004981709380001@news.ni.net>
1998-05-05  0:00     ` Stephen Leake
1998-05-05  0:00       ` Matthew Heaney
1998-05-06  0:00         ` Stephen Leake
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox