comp.lang.ada
 help / color / mirror / Atom feed
From: ncohen@watson.ibm.com (Norman H. Cohen)
Subject: Re: Translate this into Ada ...
Date: 1996/08/21
Date: 1996-08-21T00:00:00+00:00	[thread overview]
Message-ID: <4vfb15$ujr@watnews1.watson.ibm.com> (raw)
In-Reply-To: 3219E6E2.2F5@eurocontrol.fr


In article <3219E6E2.2F5@eurocontrol.fr>, Richard Irvine
<Richard.Irvine@eurocontrol.fr> writes:

|> We would like all lists in an application to be read using an iterator
|> with operations like:
|>
|>   function  theCurrentItem( theIterator :        Iterator ) return
|> ItemType;
|>   function  atTheEnd      ( theIterator :        Iterator ) return
|> Boolean;
|>   procedure goToTheNext   ( theIterator : in out Iterator );
|>
|> Furthermore, since an iterator has to be created for a particular list
|> and since the implementation of an iterator is dependent on that of the
|> list
|> we would like all list types to have a (constructor) operation like
|>
|>   function  aNewIteratorFor( theList : List ) return Iterator;
|>
|> This design decision should apply to all types of list, regardless of
|> the ItemType and regardless of the implementation of the lists.

One approach is a generic, each instance of which declares a root
abstract type for collections and a root abstract type for iterators.
The instance declares all of the above operations as abstract
subprograms.

The package in which you declare your list type derives both a new list
type from the root abstract collection type and a new iterator type from
the root abstract iterator type.  It provides concrete subprograms to
override each of the inherited abstract operations.  Since the concrete
collection type and the concrete iterator type are declared in the same
package, the bodies for these operations have access to the
implementations for both concrete types.

Here is a generic template like that I have described:

   generic

      type Item_Type (<>) is limited private;

   package Generic_Abstract_Collections is

      type Collection_Type is abstract tagged private;
      type Iterator_Type is abstract tagged private;

      function New_Iterator_For
         (Collection: Collection_Type) return Iterator_Type'Class
         is abstract;

      function Current_Item (Iterator: Iterator_Type) return Item_Type
         is abstract;

      function At_The_End (Iterator: Iterator_Type) return Boolean
         is abstract;

      procedure Advance (Iterator: in out Iterator_Type) is abstract;

      Iterator_Error: exception;
         -- Raised by Current_Item or Advance invoked with an iterator that is
         --    not currently positioned at an item.
   private

      type Collection_Type is abstract tagged null record;
      type Iterator_Type is abstract tagged null record;

   end Generic_Abstract_Collections;


(New_Iterator_For has a classwide result because it is not permitted to
be a primitive operation of more than one tagged type.)  Here is a sample
application, to a collection of integers implemented as a linked list:


   with Generic_Abstract_Collections;

   package Integer_Lists is

      package Abstract_Integer_Collections is
         new Generic_Abstract_Collections (Item_Type => Integer);

      type Integer_List_Type is
         new Abstract_Integer_Collections.Collection_Type with private;

      type Integer_List_Iterator_Type is
         new Abstract_Integer_Collections.Iterator_Type with private;

      Iterator_Error: exception renames
                         Abstract_Integer_Collections.Iterator_Error;

      -- Concrete subprograms to override inherited abstract subprograms:

      function New_Iterator_For
         (Collection: Integer_List_Type)
         return Abstract_Integer_Collections.Iterator_Type'Class;

      function Current_Item
         (Iterator: Integer_List_Iterator_Type) return Integer;

      function At_The_End
         (Iterator: Integer_List_Iterator_Type) return Boolean;

      procedure Advance (Iterator: in out Integer_List_Iterator_Type);

      -- Other Integer_List_Type operations could be declared here.

   private

      type Cell_Type;
      type Cell_Pointer_Type is access Cell_Type;
      type Cell_Type is
         record
            Value : Integer;
            Link  : Cell_Pointer_Type;
         end record;

      type Integer_List_Type is
         new Abstract_Integer_Collections.Collection_Type with
            record
               First_Cell: Cell_Pointer_Type;
            end record;

      type Integer_List_Iterator_Type is
         new Abstract_Integer_Collections.Iterator_Type with
            record
               Next_Cell: Cell_Pointer_Type := null;
            end record;

   end Integer_Lists;


   package body Integer_Lists is

      function New_Iterator_For
         (Collection: Integer_List_Type)
         return Abstract_Integer_Collections.Iterator_Type'Class is
      begin
         return Integer_List_Iterator_Type'
            (Abstract_Integer_Collections.Iterator_Type with
             Next_Cell => Collection.First_Cell);
      end New_Iterator_For;

      function Current_Item
         (Iterator: Integer_List_Iterator_Type) return Integer is
      begin
         if Iterator.Next_Cell = null then
            raise Iterator_Error;
         else
            return Iterator.Next_Cell.Value;
         end if;
      end Current_Item;

      function At_The_End (Iterator: Integer_List_Iterator_Type) return Boolean is
      begin
         return Iterator.Next_Cell = null;
      end At_The_End;

      procedure Advance (Iterator: in out Integer_List_Iterator_Type) is
      begin
         if Iterator.Next_Cell = null then
            raise Iterator_Error;
         else
            Iterator.Next_Cell := Iterator.Next_Cell.Link;
         end if;
      end Advance;

      -- [Bodies of other Integer_List_Type operations.]

   end Integer_Lists;

Note that the return type of New_Iterator_For is the classwide type for
the root Iterator_Type declared in the generic instance (i.e., the return
type for the version of New_Iterator_For inherited by Integer_List_Type),
not for the derived type Integer_List_Iterator_Type.  However, the
function body returns an Integer_List_Iterator_Type object.

It might be more appropriate to make Iterator_Type limited (since it
represents the state of an in-progress loop iteration, something that it
does not make sense to copy).  In this case, the New_Iterator_For
function should be replaced by a procedure Start_Iteration with an out
parameter of Iterator_Type.  Also, if operations are provided to insert
items in or delete items from a collection, a decision must be made about
the semantics of iterating over a list while it is being updated, and the
implementation of iterators must account for insertions and deletions
during iteration.

--
Norman H. Cohen    ncohen@watson.ibm.com




  reply	other threads:[~1996-08-21  0:00 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-08-20  0:00 Translate this into Ada Richard Irvine
1996-08-21  0:00 ` Norman H. Cohen [this message]
1996-08-22  0:00   ` Richard Irvine
1996-08-22  0:00     ` Richard Irvine
1996-08-22  0:00     ` Norman H. Cohen
1996-08-29  0:00   ` Robert A Duff
1996-08-21  0:00 ` David Weller
  -- strict thread matches above, loose matches on Subject: below --
1996-08-21  0:00 Spasmo
1996-08-21  0:00 ` Richard Irvine
1996-08-28  0:00   ` Robert A Duff
replies disabled

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