Iterators implement another "competitive" approach to the cursor concept. So one can write very simply a special TABLE_ITERATOR_ which extracts for example all elements with a key smaller than 50 into another table. As another possible name of this class we considered TOOLS - additionals tools to be applied on containers. The base idea is that each ITERATOR_ should redefine routines 'test' (delivering True by default) and 'action' (by default it is empty) to fit the programmer's needs. Beside this it may be possible to extend the ITERATOR_ possibility by another routines - the routines we defined can be used as a starting point. We only want to remind you to keep in mind that such extensions should be selected very carefully.
indexing title: "Alternative facilities for traversing the containers" deferred class interface ITERATOR_ feature -- Operations action -- you can redefine this procedure to put all the operations -- which should be done on every entry of the container being -- traversed; the current entry is accessible through queries -- 'item' and 'key' - the latter one is only for the tables require proper_target: target /= Void do_all -- procedure action will be performed on every entry of the -- container being traversed unconditionally require proper_target: target /= Void do_if -- procedure action will be performed on every entry of the -- container being traversed if it satisfies query 'test'; -- "testing" is performing on every entry automatically ... require proper_target: target /= Void do_until -- procedure action will be performed on every entry of the -- container being traversed - one after another - until query -- 'test' gives True; every entry is being "tested" automatically require proper_target: target /= Void do_while -- procedure action will be performed on every entry of the -- container being traversed - one after another - while query -- 'test' is giving True; every entry is being "tested" -- automatically require proper_target: target /= Void feature -- Queries target: TRAVERSABLE_ -- the container is being traversed deferred test: BOOLEAN -- you can redefine this query to put the conditions which should -- be applied to every entry of the container - one after another; -- the current entry is accessible through queries 'item' and -- 'key' - the latter one is only for the tables require proper_target: target /= Void end
indexing title: "List iterators: tools for traversing the lists% % (except the lists of class SIMPLE_LIST_)" class interface LIST_ITERATOR_[G] inherit ITERATOR_ feature -- Operations attach (x: LIST_[G]) -- selects the target for traversal require proper_list: x /= Void ensure well_done: target /= Void feature -- Queries extract_list: like target -- delivers all the entries of the list attached which are -- satisfied the conditions put by 'test' require proper_target: target /= Void target: LIST_[G] -- the structure to be traversed feature {NONE} -- Implementation item: G -- delivers the current entry for "being touched" in features -- 'action' and 'test' while traversing the list end
indexing title: "Table iterators: tools for traversing the tables" class interface TABLE_ITERATOR_[G, H] inherit ITERATOR_ feature -- Operations attach (x: TABLE_[G, H]) -- selects the target for traversal require proper_table: x /= Void feature -- Queries extract_list: LIST_[G] -- delivers all the elements or items of the table attached the -- entries of which including the keys satisfying the -- conditions put by 'test' require proper_target: target /= Void extract_table: like target -- delivers all the entries of the table attached which are -- satisfied the conditions put by 'test' require proper_target: target /= Void target: TABLE_[G, H] -- the structure to be traversed feature {NONE} -- Implementation item: G -- delivers the element or item of the current entry for -- "being touched" in features 'action' and 'test' while -- traversing the table key: H -- delivers the key of the current entry for "being touched" -- in features 'action' and 'test' while traversing the table end
A simple example for such a tool is a report writer. It looks like this:
class REPORT inherit LIST_ITERATOR_[CUSTOMER] redefine action, test end creation make feature fmt: STRING is "%n!20s !20s !10.2d" hdr: STRING is "%n%n!s%n!20s !20s !10s" zip: INTEGER sio: SCIENTIFIC_FORMAT make (title: STRING; p: INTEGER) is do !!sio.make sio.printf (hdr, <<title, "name", "town", "salary">>) zip := p end test (x: CUSTOMER): BOOLEAN is do Result := (x.zip_code = zip) end action (x: CUSTOMER) is do sio.printf (fmt, <<x.name + " " + x.first_name, x.town, x.salary >>) end end -- class REPORT
This report might be called as follows:
... l, lx: LIST_[CUSTOMER]; r: REPORT; !!l.make; -- -- putting some data into the list ... -- !!r.make ("All customers with zip code", 12345); r.attach (l); r.do_if; !!r.make ("All customers with zip code", 35619"); r.attach (l); lx := r.extract_list; -- delivers the list of all customers -- with zip code 35619 .. ...
There is no doubt that the same class can be programmed using cursors. The reason that we introduce both versions in our class concept is the same why we use lists and tables: it is possible to live without tables - but in many cases tables are very convenient. The same is true with the ITERATOR_ classes. At least this container library should serve the programmer's need. Please note that features 'extract...' work like filters, i.e. that only those elements are included which fulfill the condition of the actual tool.