mirror of
https://github.com/EiffelSoftware/eiffel-org.git
synced 2025-12-08 15:52:26 +01:00
Removed first slash in [[ref:libraries/...]] wiki links.
git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1612 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
@@ -8,7 +8,7 @@ A container can be studied from three viewpoints: access, storage and traversal.
|
||||
* The '''storage''' criterion affects how the items are put together. For example some containers are finite, others potentially infinite; among finite structures, some are bounded, others unbounded.
|
||||
* The '''traversal''' criterion affects how, if in any way, the items of a container can be traversed. A traversal is a mechanism which makes it possible to examine each item of a container once, in a clearly specified order. For example some containers can be traversed sequentially, in one direction or two; tree structures lend themselves to preorder, postorder and breadth-first traversals.
|
||||
|
||||
For each of these criteria the Base library offers a single-inheritance hierarchy of deferred classes. The top of the access hierarchy is class [[ref:libraries/base/reference/collection_chart|COLLECTION]] ; the top of the storage hierarchy is class [[ref:/libraries/base/reference/box_chart|BOX]] ; the top of the traversal hierarchy is class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] . These three classes are heirs of the most general class [[ref:libraries/base/reference/container_chart|CONTAINER]] .
|
||||
For each of these criteria the Base library offers a single-inheritance hierarchy of deferred classes. The top of the access hierarchy is class [[ref:libraries/base/reference/collection_chart|COLLECTION]] ; the top of the storage hierarchy is class [[ref:libraries/base/reference/box_chart|BOX]] ; the top of the traversal hierarchy is class [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] . These three classes are heirs of the most general class [[ref:libraries/base/reference/container_chart|CONTAINER]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
[[Property:title|EiffelBase Data Structures, Lists]]
|
||||
[[Property:weight|1]]
|
||||
[[Property:uuid|23f540e0-16d5-807c-30af-74d3416a5709]]
|
||||
Many applications need sequential structures, also called linear structures, in particular lists and circular chains. Apart from three classes describing individual list cells, all the classes involved are descendants of class [[ref:/libraries/base/reference/linear_chart|LINEAR]] , one of the deferred classes describing general traversal properties and introduced in the chapter that described the general data structure taxonomy. More precisely, all but one of the classes of interest for the present discussion are descendants, direct or indirect, from a class called [[ref:/libraries/base/reference/chain_chart|CHAIN]] which describes general sequential structures possessing a cursor as well as insertion properties. The exception is class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] , which describes infinite structures; all the others describe finite structures. <br/>
|
||||
[[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] , which describes a more general notion of sequence. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] . There are two main categories of sequential structures: some, called circular chains, are cyclic; others, called lists, are not. Another distinction exists between dynamic structures, which may be extended at will, and fixed ones, which have a bounded capacity. <br/>
|
||||
Many applications need sequential structures, also called linear structures, in particular lists and circular chains. Apart from three classes describing individual list cells, all the classes involved are descendants of class [[ref:libraries/base/reference/linear_chart|LINEAR]] , one of the deferred classes describing general traversal properties and introduced in the chapter that described the general data structure taxonomy. More precisely, all but one of the classes of interest for the present discussion are descendants, direct or indirect, from a class called [[ref:libraries/base/reference/chain_chart|CHAIN]] which describes general sequential structures possessing a cursor as well as insertion properties. The exception is class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] , which describes infinite structures; all the others describe finite structures. <br/>
|
||||
[[ref:libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] , which describes a more general notion of sequence. [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] is a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] . There are two main categories of sequential structures: some, called circular chains, are cyclic; others, called lists, are not. Another distinction exists between dynamic structures, which may be extended at will, and fixed ones, which have a bounded capacity. <br/>
|
||||
In all of the structures under review you may insert two or more occurrences of a given item in such a way that the occurrences are distinguishable. In other words, the structures are bags rather than just sets, although it is possible to use them to implement sets.
|
||||
|
||||
=Higher Level Traversal Classes=
|
||||
|
||||
The list and chain classes are characterized, for their traversal properties, as being linear and, more precisely, bilinear. In the traversal hierarchy, the relevant deferred classes are [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , introduced in the [[EiffelBase, Abstract Container Structures: The Taxonomy|discussion]] of the general taxonomy.
|
||||
The list and chain classes are characterized, for their traversal properties, as being linear and, more precisely, bilinear. In the traversal hierarchy, the relevant deferred classes are [[ref:libraries/base/reference/linear_chart|LINEAR]] and [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , introduced in the [[EiffelBase, Abstract Container Structures: The Taxonomy|discussion]] of the general taxonomy.
|
||||
|
||||
==Linear structures==
|
||||
|
||||
[[ref:/libraries/base/reference/linear_chart|LINEAR]] describes sequential structures that may be traversed one way. It introduces in particular the following features, illustrated on the figure below:
|
||||
[[ref:libraries/base/reference/linear_chart|LINEAR]] describes sequential structures that may be traversed one way. It introduces in particular the following features, illustrated on the figure below:
|
||||
* <eiffel>after</eiffel>, a boolean-valued query which determines whether you have moved past the last position (a more precise specification is given below).
|
||||
* <eiffel>off</eiffel>, a boolean-valued query which is false if and only if there is no item at the current position; for [[ref:/libraries/base/reference/linear_chart|LINEAR]] this is the same as:
|
||||
* <eiffel>off</eiffel>, a boolean-valued query which is false if and only if there is no item at the current position; for [[ref:libraries/base/reference/linear_chart|LINEAR]] this is the same as:
|
||||
<code>is_empty and not after</code>
|
||||
|
||||
* <eiffel>item</eiffel>, a query which returns the item at the current position - provided of course there is one, as expressed by the precondition:
|
||||
@@ -32,11 +32,11 @@ The list and chain classes are characterized, for their traversal properties, as
|
||||
|
||||
There is also a procedure <eiffel>search</eiffel> with one argument, which determines whether the value of that argument appears in the structure at or after the current position, and if not makes <eiffel>after</eiffel> become true. This procedure is internally used by the default implementation of the <eiffel>has</eiffel> function (the general membership test) for linear structures. Like has for all containers, <eiffel>search</eiffel> uses object or reference equality depending on the value set for <eiffel>object_comparison</eiffel>.
|
||||
|
||||
An invariant property of [[ref:/libraries/base/reference/linear_chart|LINEAR]] structures is that the current position may go off one step past the last item if any, but no further. The precondition of <eiffel>forth</eiffel> - not after - helps ensure this. The first item (if any) being at position 1, the maximum allowable position is <eiffel>count</eiffel> + 1, where <eiffel>count</eiffel> is the number of items.
|
||||
An invariant property of [[ref:libraries/base/reference/linear_chart|LINEAR]] structures is that the current position may go off one step past the last item if any, but no further. The precondition of <eiffel>forth</eiffel> - not after - helps ensure this. The first item (if any) being at position 1, the maximum allowable position is <eiffel>count</eiffel> + 1, where <eiffel>count</eiffel> is the number of items.
|
||||
|
||||
==Bilinear structures==
|
||||
|
||||
[[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] describes linear structures which may be traversed both ways. It inherits from [[ref:/libraries/base/reference/linear_chart|LINEAR]] and extends it with two new features which ensure complete symmetry between the two directions of movement:
|
||||
[[ref:libraries/base/reference/bilinear_chart|BILINEAR]] describes linear structures which may be traversed both ways. It inherits from [[ref:libraries/base/reference/linear_chart|LINEAR]] and extends it with two new features which ensure complete symmetry between the two directions of movement:
|
||||
* <eiffel>before</eiffel>, a boolean-valued query which determines whether you have moved to the left of the first position (a more precise specification is given below).
|
||||
* <eiffel>back</eiffel>, a command to move backward by one position; the precondition is not before.
|
||||
|
||||
@@ -48,20 +48,20 @@ For bilinear structures the position can range between 0 (not just 1) and count
|
||||
|
||||
==Invariant properties for after, before and off==
|
||||
|
||||
The redefinition of <eiffel>off</eiffel> illustrates a general methodological advice about invariants: be careful about not over-constraining the invariant by including properties that may be made more general in descendants. It might have been tempting to include in [[ref:/libraries/base/reference/linear_chart|LINEAR]] an invariant clause of the form
|
||||
The redefinition of <eiffel>off</eiffel> illustrates a general methodological advice about invariants: be careful about not over-constraining the invariant by including properties that may be made more general in descendants. It might have been tempting to include in [[ref:libraries/base/reference/linear_chart|LINEAR]] an invariant clause of the form
|
||||
<code>
|
||||
off = is_empty or after</code>
|
||||
|
||||
This property, however, would be too constraining. More precisely, it is always true that the right-hand side implies the left-hand-side: if a linear structure is either empty or after, then it is off. But the converse is not true, since certain kinds of linear structure, for example bilinear ones, may be off but neither empty nor after. <br/>
|
||||
The actual invariant for class [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] is obtained in three stages. In class [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] the feature off is deferred and a basic property of that feature is expressed by the invariant clause
|
||||
The actual invariant for class [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] is obtained in three stages. In class [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] the feature off is deferred and a basic property of that feature is expressed by the invariant clause
|
||||
<code>
|
||||
empty_constraint:is_empty implies off</code>
|
||||
|
||||
In [[ref:/libraries/base/reference/linear_chart|LINEAR]] , feature <eiffel>off</eiffel> is effected through an implementation which returns the value of the expression <eiffel>is_empty</eiffel> or <eiffel>after</eiffel>. The class adds an invariant clause which, however, says less than the implementation to leave some room for variation:
|
||||
In [[ref:libraries/base/reference/linear_chart|LINEAR]] , feature <eiffel>off</eiffel> is effected through an implementation which returns the value of the expression <eiffel>is_empty</eiffel> or <eiffel>after</eiffel>. The class adds an invariant clause which, however, says less than the implementation to leave some room for variation:
|
||||
<code>
|
||||
after_constraint:after implies off</code>
|
||||
|
||||
Finally [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , an heir of [[ref:/libraries/base/reference/linear_chart|LINEAR]] , redefines <eiffel>off</eiffel> to return the value of the expression
|
||||
Finally [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , an heir of [[ref:libraries/base/reference/linear_chart|LINEAR]] , redefines <eiffel>off</eiffel> to return the value of the expression
|
||||
<code>
|
||||
before or after</code>
|
||||
|
||||
@@ -73,7 +73,7 @@ The new implementation of <eiffel>off</eiffel>
|
||||
<code>
|
||||
after or before</code>
|
||||
|
||||
would not guarantee the invariant clause inherited from [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] were it not for another clause introduced in [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] :
|
||||
would not guarantee the invariant clause inherited from [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] were it not for another clause introduced in [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] :
|
||||
<code>
|
||||
empty_property: is_empty implies (after or before )</code>
|
||||
|
||||
@@ -81,7 +81,7 @@ which indicates that an empty bilinear structure must always be <eiffel>after</e
|
||||
<code>
|
||||
not_both: not(after and before)</code>
|
||||
|
||||
The flat-short form of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] shows the complete reconstructed invariant:
|
||||
The flat-short form of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] shows the complete reconstructed invariant:
|
||||
<code>
|
||||
not_both: not (after and before)
|
||||
empty_property: is_empty implies (after or before)
|
||||
@@ -104,13 +104,13 @@ For a more general form of this scheme, applicable to circular chains as well as
|
||||
end</code>
|
||||
|
||||
The value of <code>lin.off</code> is always true for an empty structure, so in this case the loop will, correctly, execute only its initialization actions if present. <br/>
|
||||
This is a very common pattern, which you will find in the library classes themselves (for example has is implemented in this way) and many application clients. The iterator classes corresponding to linear structures ([[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ) turn this pattern and several related ones into actual reusable routines. <br/>
|
||||
This is a very common pattern, which you will find in the library classes themselves (for example has is implemented in this way) and many application clients. The iterator classes corresponding to linear structures ([[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ) turn this pattern and several related ones into actual reusable routines. <br/>
|
||||
For bilinear structures there is another traversal mechanism going backward rather than forward; it is the same as above except that <eiffel>finish</eiffel> replaces <eiffel>start</eiffel> and <eiffel>back</eiffel> replaces <eiffel>finish</eiffel>. The exit condition remains <eiffel>off</eiffel> since <eiffel>before</eiffel>, like <eiffel>after</eiffel>, implies <eiffel>off</eiffel>.
|
||||
|
||||
==A precise view of after and before==
|
||||
|
||||
Getting the specification of <eiffel>after</eiffel> and before <eiffel>right</eiffel>, so that it will handle all cases properly, requires some care. <br/>
|
||||
For every one of the structures under discussion there is a notion of current position, which we may call the cursor position even though for the moment the cursor is a virtual notion only. (Actual cursor objects will come later when we combine [[ref:/libraries/base/reference/linear_chart|LINEAR]] , [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] and other classes from the traversal hierarchy with [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] and other classes from the collection hierarchy.) The informal definition is that <eiffel>after</eiffel> is true if and only if the cursor - in this informal sense of a fictitious marker signaling the current position - is one position after the last item, if any, and that <eiffel>before</eiffel> is true if and only if the cursor is one position before the first item. When the cursor is on any of the items, <eiffel>after</eiffel> and <eiffel>before</eiffel> are false; <eiffel>after</eiffel> holds when the cursor is to the right of the last item, and <eiffel>before</eiffel> when it is to the left of the first item. This leaves open the question of what conventions to take for an empty structure. If iteration schemes of the above type are to work, then <eiffel>after</eiffel> must be true for an empty structure. For a bilinear structure, however, we should have total symmetry between the two pairs of features
|
||||
For every one of the structures under discussion there is a notion of current position, which we may call the cursor position even though for the moment the cursor is a virtual notion only. (Actual cursor objects will come later when we combine [[ref:libraries/base/reference/linear_chart|LINEAR]] , [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] and other classes from the traversal hierarchy with [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] and other classes from the collection hierarchy.) The informal definition is that <eiffel>after</eiffel> is true if and only if the cursor - in this informal sense of a fictitious marker signaling the current position - is one position after the last item, if any, and that <eiffel>before</eiffel> is true if and only if the cursor is one position before the first item. When the cursor is on any of the items, <eiffel>after</eiffel> and <eiffel>before</eiffel> are false; <eiffel>after</eiffel> holds when the cursor is to the right of the last item, and <eiffel>before</eiffel> when it is to the left of the first item. This leaves open the question of what conventions to take for an empty structure. If iteration schemes of the above type are to work, then <eiffel>after</eiffel> must be true for an empty structure. For a bilinear structure, however, we should have total symmetry between the two pairs of features
|
||||
* <eiffel>start</eiffel>, <eiffel>forth</eiffel>, <eiffel>after</eiffel>.
|
||||
* <eiffel>finish</eiffel>, <eiffel>back</eiffel>, <eiffel>before</eiffel>.
|
||||
|
||||
@@ -128,7 +128,7 @@ When a structure is created, some initializations will have to be made; the defa
|
||||
<code>
|
||||
if after and not is_empty then...</code>
|
||||
|
||||
The solution finally retained for the Base libraries uses a different technique, which has turned out to be preferable. The idea is to replace the conceptual picture by one in which there are always two fictitious sentinel items. The two sentinel items are only present conceptually. They are of course not taken into account for the computation of <eiffel>count</eiffel> and, although it is possible to conceive of an implementation which would actually reserve space for them (for example in an array representation), none of the implementations used in Base for the classes of this documentation and other descendants of [[ref:/libraries/base/reference/linear_chart|LINEAR]] do. The only purpose of the sentinels is to provide two valid theoretical cursor positions, which exist regardless of the number of actual (non-sentinel) items in the structure. <br/>
|
||||
The solution finally retained for the Base libraries uses a different technique, which has turned out to be preferable. The idea is to replace the conceptual picture by one in which there are always two fictitious sentinel items. The two sentinel items are only present conceptually. They are of course not taken into account for the computation of <eiffel>count</eiffel> and, although it is possible to conceive of an implementation which would actually reserve space for them (for example in an array representation), none of the implementations used in Base for the classes of this documentation and other descendants of [[ref:libraries/base/reference/linear_chart|LINEAR]] do. The only purpose of the sentinels is to provide two valid theoretical cursor positions, which exist regardless of the number of actual (non-sentinel) items in the structure. <br/>
|
||||
The sentinel items always appear at positions 0 and <eiffel>count</eiffel> + 1; this property is true even if the structure is empty of items, in which case count is zero. As a result, the following properties are part of the invariant:
|
||||
<code>
|
||||
0 <= index
|
||||
@@ -151,22 +151,22 @@ Finally, the only way to make delicate design decisions is to express the issues
|
||||
|
||||
=Sequences And Chains=
|
||||
|
||||
Still deferred, classes [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] and[[ref:/libraries/base/reference/chain_chart|CHAIN]] provide the basis for all list and chain classes, as well as for many trees and for dispensers. <br/>
|
||||
SEQUENCE is constructed with the full extent of the technique described in the discussion of the taxonomy: using multiple inheritance to combine one class each from the access, traversal and storage hierarchy. [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] indeed has three parents:
|
||||
* [[ref:/libraries/base/reference/active_chart|ACTIVE]] gives the access properties. A sequence is an active structure with a notion of current item. Remember that active structures are a special case of bags.
|
||||
* [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , as studied above, indicates that a sequence may be traversed both ways.
|
||||
* FINITE, from the storage hierarchy, indicates that the class describes finite sequences. (A class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] is also present, as described below.)
|
||||
Still deferred, classes [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] and[[ref:libraries/base/reference/chain_chart|CHAIN]] provide the basis for all list and chain classes, as well as for many trees and for dispensers. <br/>
|
||||
SEQUENCE is constructed with the full extent of the technique described in the discussion of the taxonomy: using multiple inheritance to combine one class each from the access, traversal and storage hierarchy. [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] indeed has three parents:
|
||||
* [[ref:libraries/base/reference/active_chart|ACTIVE]] gives the access properties. A sequence is an active structure with a notion of current item. Remember that active structures are a special case of bags.
|
||||
* [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , as studied above, indicates that a sequence may be traversed both ways.
|
||||
* FINITE, from the storage hierarchy, indicates that the class describes finite sequences. (A class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] is also present, as described below.)
|
||||
|
||||
To the features of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] principally adds features for adding, changing and removing items. A few procedures in particular serve to insert items at the end:
|
||||
To the features of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] principally adds features for adding, changing and removing items. A few procedures in particular serve to insert items at the end:
|
||||
* <code>s .put ( v )</code> adds v at the end of a sequence s.
|
||||
* <eiffel> extend</eiffel> and <eiffel>force</eiffel>, at the [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] level, do the same as <eiffel>put</eiffel>.
|
||||
* <eiffel> extend</eiffel> and <eiffel>force</eiffel>, at the [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] level, do the same as <eiffel>put</eiffel>.
|
||||
* <code>s .append ( s1 )</code> adds to the end of s the items of s1 (another sequence), preserving their s1 order.
|
||||
|
||||
Other procedures work on the current position:
|
||||
* <code>s.</code><eiffel>remove</eiffel> removes the item at current position.
|
||||
* <code>s.replace ( v )</code> replaces by v the item at current position.
|
||||
|
||||
SEQUENCE, however, does not provide a procedure to insert an item at the current position, since not all implementations of sequences support this possibility; you will find it in descendants of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] seen below. <br/>
|
||||
SEQUENCE, however, does not provide a procedure to insert an item at the current position, since not all implementations of sequences support this possibility; you will find it in descendants of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] seen below. <br/>
|
||||
Yet another group of features are based on the first occurrence of a certain item, or on all occurrences:
|
||||
* <code>s.prune ( v ) removes the first occurrence of v in s</code>, if any.
|
||||
* <code>s.prune_all ( v ) removes all occurrences of v</code>.
|
||||
@@ -176,16 +176,16 @@ These procedures have various abstract preconditions: <code>s .extendible for ad
|
||||
==Chains==
|
||||
|
||||
Chains are sequences with a few more properties: items may be accessed through their indices, and it is possible to define cursor objects attached to individual items. <br/>
|
||||
Class [[ref:/libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . It gets its access properties from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] (which adds the notion of cursor to the features of [[ref:/libraries/base/reference/active_chart|ACTIVE]] , already present in [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] ) and is also an heir of [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] . This ancestry implies in particular the presence of the following features:
|
||||
* <eiffel>cursor</eiffel>, from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which makes it possible to keep a reference to an item of the structure.
|
||||
* <eiffel>i_th</eiffel> and <eiffel>put_i_th</eiffel> from [[ref:/libraries/base/reference/table_chart|TABLE]] , via [[ref:/libraries/base/reference/indexable_chart|INDEXABLE]] , which make it possible to access and replace the value of an item given by its integer index.
|
||||
Class [[ref:libraries/base/reference/chain_chart|CHAIN]] is an heir of [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] . It gets its access properties from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] (which adds the notion of cursor to the features of [[ref:libraries/base/reference/active_chart|ACTIVE]] , already present in [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] ) and is also an heir of [[ref:libraries/base/reference/indexable_chart|INDEXABLE]] . This ancestry implies in particular the presence of the following features:
|
||||
* <eiffel>cursor</eiffel>, from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which makes it possible to keep a reference to an item of the structure.
|
||||
* <eiffel>i_th</eiffel> and <eiffel>put_i_th</eiffel> from [[ref:libraries/base/reference/table_chart|TABLE]] , via [[ref:libraries/base/reference/indexable_chart|INDEXABLE]] , which make it possible to access and replace the value of an item given by its integer index.
|
||||
|
||||
These features were called <eiffel>item</eiffel> and <eiffel>put</eiffel> in [[ref:/libraries/base/reference/table_chart|TABLE]] , but are renamed here to remove the conflict with homonymous features from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] . <br/>
|
||||
Procedure <eiffel>put</eiffel> for chains is the version obtained from [[ref:/libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which has the same effect as <eiffel>replace</eiffel> - replacing the value of the item at cursor position. The <eiffel>put</eiffel> procedure from [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] is renamed <eiffel>sequence_ put</eiffel>. This feature is not exported by [[ref:/libraries/base/reference/chain_chart|CHAIN]] , however, since its effect (adding an item at the end) may be obtained through the simpler name <eiffel>extend</eiffel>.
|
||||
These features were called <eiffel>item</eiffel> and <eiffel>put</eiffel> in [[ref:libraries/base/reference/table_chart|TABLE]] , but are renamed here to remove the conflict with homonymous features from [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] . <br/>
|
||||
Procedure <eiffel>put</eiffel> for chains is the version obtained from [[ref:libraries/base/reference/cursor_structure_chart|CURSOR_STRUCTURE]] , which has the same effect as <eiffel>replace</eiffel> - replacing the value of the item at cursor position. The <eiffel>put</eiffel> procedure from [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] is renamed <eiffel>sequence_ put</eiffel>. This feature is not exported by [[ref:libraries/base/reference/chain_chart|CHAIN]] , however, since its effect (adding an item at the end) may be obtained through the simpler name <eiffel>extend</eiffel>.
|
||||
|
||||
==Dynamic chains==
|
||||
|
||||
By default, chains can only be extended at the end, through <eiffel>extend</eiffel> and <eiffel>sequence_put</eiffel>. Of particular interest are those chains where clients can insert and remove items at any position. Such chains are said to be dynamic, and described by [[ref:/libraries/base/reference/chain_chart|CHAIN]] 's heir [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] . The new features are predictable:
|
||||
By default, chains can only be extended at the end, through <eiffel>extend</eiffel> and <eiffel>sequence_put</eiffel>. Of particular interest are those chains where clients can insert and remove items at any position. Such chains are said to be dynamic, and described by [[ref:libraries/base/reference/chain_chart|CHAIN]] 's heir [[ref:libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] . The new features are predictable:
|
||||
* Procedure <eiffel>put_front</eiffel> adds an item before the first. (As noted, the procedures to add an item after the last are already available in chains.)
|
||||
* Procedures <eiffel>put_left</eiffel> and <eiffel>put_right</eiffel> add an item at the left and right of the cursor position.
|
||||
* Procedures <eiffel>remove_left</eiffel> and remove_right remove an item at the left and right or the cursor position.
|
||||
@@ -198,17 +198,17 @@ The class also provides implementations of <eiffel>prune</eiffel>, <eiffel>prune
|
||||
A chain is a finite sequential structure. This property means that items are arranged in a linear order and may be traversed from the first to the last. To do this you may use a loop of the form shown above, based on procedures <eiffel>start</eiffel> and <eiffel>forth</eiffel>. <br/>
|
||||
This property leaves room for several variants. In particular chains may be straight or circular.
|
||||
* A straight chain, which from now on will be called a list, has a beginning and an end.
|
||||
* A circular chain, as represented by class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] and its descendants, has a much more flexible notion of first item. It is organized so that every item has a successor.
|
||||
* A circular chain, as represented by class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] and its descendants, has a much more flexible notion of first item. It is organized so that every item has a successor.
|
||||
|
||||
This representation is conceptual only; in fact the implementations of circular chains found in the Base libraries are based on lists, implemented in one of the ways described below (in particular linked and arrayed). <br/>
|
||||
The major originality of circular chains is that unless the structure is empty procedure <eiffel>forth</eiffel> is always applicable: it will cycle past the last item, coming back to the <br/>
|
||||
first. The symmetric property applies to <eiffel>back</eiffel>. The cyclic nature of <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular chains is expressed precisely by the assertions. The version of <eiffel>forth</eiffel> for class [[ref:/libraries/base/reference/chain_chart|CHAIN]] , which comes from [[ref:/libraries/base/reference/linear_chart|LINEAR]] , has precondition
|
||||
first. The symmetric property applies to <eiffel>back</eiffel>. The cyclic nature of <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular chains is expressed precisely by the assertions. The version of <eiffel>forth</eiffel> for class [[ref:libraries/base/reference/chain_chart|CHAIN]] , which comes from [[ref:libraries/base/reference/linear_chart|LINEAR]] , has precondition
|
||||
<code>not after</code>
|
||||
|
||||
Similarly, the precondition for back is
|
||||
<code>not before</code>
|
||||
|
||||
For lists, after becomes true when the cursor moves past the last item. For circular chains, however, after and before are never true except for an empty structure; this is expressed by the invariant clauses of class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] :
|
||||
For lists, after becomes true when the cursor moves past the last item. For circular chains, however, after and before are never true except for an empty structure; this is expressed by the invariant clauses of class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] :
|
||||
<code>not before</code>
|
||||
|
||||
For a non-empty circular chain, then, you can circle forever around the items, using forth or back.
|
||||
@@ -218,7 +218,7 @@ For a non-empty circular chain, then, you can circle forever around the items, u
|
||||
For a list, the first and last items are fixed, and correspond to specific places in the physical representation. <br/>
|
||||
A circular chain also needs a notion of first item, if only to enable a client to initiate a traversal through procedure start. Similarly, there is a last item - the one just before the first in a cyclic traversal. (If the chain has just one item, it is both first and last.) <br/>
|
||||
For circular chains, however, there is no reason why the first item should always remain the same. One of the benefits that clients may expect from the use of a circular <br/>
|
||||
structure is the ability to choose any item as the logical first. Class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] offers for that purpose the procedure <eiffel>set_start</eiffel> which designates the current cursor position as the first in the circular chain. Subsequent calls to <eiffel>start</eiffel> will move the cursor to this position; calls to <eiffel>finish</eiffel> will move the cursor to the cyclically preceding position. With most implementations, there will then be two notions of first position: the logical first, which clients may freely choose through calls to <eiffel>set_start</eiffel>; and the <eiffel>physical first</eiffel>, which results from the implementation. In a representation using an array with indices from 1 to <eiffel>capacity</eiffel>, for example, the physical first is position 1, and the logical first may be any index in the permitted range. In a linked representation, there will be a cell first element corresponding to the physical first, but the logical first is any cell in the chain. <br/>
|
||||
structure is the ability to choose any item as the logical first. Class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] offers for that purpose the procedure <eiffel>set_start</eiffel> which designates the current cursor position as the first in the circular chain. Subsequent calls to <eiffel>start</eiffel> will move the cursor to this position; calls to <eiffel>finish</eiffel> will move the cursor to the cyclically preceding position. With most implementations, there will then be two notions of first position: the logical first, which clients may freely choose through calls to <eiffel>set_start</eiffel>; and the <eiffel>physical first</eiffel>, which results from the implementation. In a representation using an array with indices from 1 to <eiffel>capacity</eiffel>, for example, the physical first is position 1, and the logical first may be any index in the permitted range. In a linked representation, there will be a cell first element corresponding to the physical first, but the logical first is any cell in the chain. <br/>
|
||||
In such cases the circular chain classes have features called <eiffel>standard_first</eiffel>, <eiffel>standard_last</eiffel>, <eiffel>standard_start</eiffel> and so on, which are not exported (so that you will not see them in the flat-short forms) but serve to implement visible features such as <eiffel>first</eiffel>, <eiffel>last</eiffel> and <eiffel>forth</eiffel>. For example a possible implementation of <eiffel>forth</eiffel> for circular chains is
|
||||
<code>forth is
|
||||
-- Move cursor to next item, cyclically.
|
||||
@@ -245,7 +245,7 @@ loop
|
||||
end</code>
|
||||
|
||||
would not work if <code>lin</code> is a non-empty circular structure: <eiffel>off</eiffel> would never become true, so that the loop would forever cycle over the structure's items. The same would apply to a loop using finish and back instead of <eiffel>start</eiffel> and <eiffel>forth</eiffel>. This behavior is the natural result of the semantics defined for <eiffel>off</eiffel> , <eiffel>forth</eiffel> and <eiffel>back</eiffel> for circular structures. But it prevents us from using these features to perform a single traversal which will visit every item once. <br/>
|
||||
Using <eiffel>exhausted</eiffel> in lieu of off solves this problem. In class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] , <eiffel>exhausted</eiffel> is an attribute which is set to false by <eiffel>start</eiffel> and <eiffel>finish</eiffel>, and is set to true by <eiffel>forth</eiffel> when advancing from the last item to the first and by <eiffel>back</eiffel> when backing up from the first item to the last. So you should write the loop as
|
||||
Using <eiffel>exhausted</eiffel> in lieu of off solves this problem. In class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] , <eiffel>exhausted</eiffel> is an attribute which is set to false by <eiffel>start</eiffel> and <eiffel>finish</eiffel>, and is set to true by <eiffel>forth</eiffel> when advancing from the last item to the first and by <eiffel>back</eiffel> when backing up from the first item to the last. So you should write the loop as
|
||||
<code>from
|
||||
lin.start
|
||||
|
||||
@@ -261,18 +261,18 @@ loop
|
||||
lin.forth
|
||||
end</code>
|
||||
|
||||
This form is applicable to all linear structures, circular or not, since <eiffel>exhausted</eiffel> is introduced in class [[ref:/libraries/base/reference/linear_chart|LINEAR]] as a function which returns the same value as <eiffel>off</eiffel> .Its redefinition into an attribute, modified by <eiffel>start</eiffel>,<eiffel> finish</eiffel>, <eiffel>forth</eiffel> and <eiffel>back</eiffel>, does not occur until class [[ref:/libraries/base/reference/circular_chart|CIRCULAR]] . <br/>
|
||||
Because <eiffel>exhausted</eiffel> is more general than <eiffel>off</eiffel> , the iteration scheme just given (and its equivalent going backwards) is preferable to the earlier one using <eiffel>off </eiffel>, especially if there is any chance that the iteration might one day be applied to a lin structure that is circular. Classes of the Iteration library, in particular [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , rely on this scheme for iterating over linear structures.
|
||||
This form is applicable to all linear structures, circular or not, since <eiffel>exhausted</eiffel> is introduced in class [[ref:libraries/base/reference/linear_chart|LINEAR]] as a function which returns the same value as <eiffel>off</eiffel> .Its redefinition into an attribute, modified by <eiffel>start</eiffel>,<eiffel> finish</eiffel>, <eiffel>forth</eiffel> and <eiffel>back</eiffel>, does not occur until class [[ref:libraries/base/reference/circular_chart|CIRCULAR]] . <br/>
|
||||
Because <eiffel>exhausted</eiffel> is more general than <eiffel>off</eiffel> , the iteration scheme just given (and its equivalent going backwards) is preferable to the earlier one using <eiffel>off </eiffel>, especially if there is any chance that the iteration might one day be applied to a lin structure that is circular. Classes of the Iteration library, in particular [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , rely on this scheme for iterating over linear structures.
|
||||
|
||||
==Dynamic structures==
|
||||
|
||||
For both lists and circular chains, the most flexible variants, said to be dynamic, allow insertions and deletions at any position. <br/>
|
||||
The corresponding classes are descendants of [[ref:/libraries/base/reference/dynamic_list_chart|DYNAMIC_LIST]] and [[ref:/libraries/base/reference/dynamic_circular_chart|DYNAMIC_CIRCULAR]] , themselves heirs of [[ref:/libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] studied above. <br/>
|
||||
The corresponding classes are descendants of [[ref:libraries/base/reference/dynamic_list_chart|DYNAMIC_LIST]] and [[ref:libraries/base/reference/dynamic_circular_chart|DYNAMIC_CIRCULAR]] , themselves heirs of [[ref:libraries/base/reference/dynamic_chain_chart|DYNAMIC_CHAIN]] studied above. <br/>
|
||||
|
||||
|
||||
==Infinite sequences==
|
||||
|
||||
Class [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCES]] , built by inheritance from [[ref:/libraries/base/reference/countable_chart|COUNTABLE]] , [[ref:/libraries/base/reference/linear_chart|LINEAR]] and [[ref:/libraries/base/reference/active_chart|ACTIVE]] , is similar to [[ref:/libraries/base/reference/sequence_chart|SEQUENCE]] but describes infinite rather than finite sequences.
|
||||
Class [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCES]] , built by inheritance from [[ref:libraries/base/reference/countable_chart|COUNTABLE]] , [[ref:libraries/base/reference/linear_chart|LINEAR]] and [[ref:libraries/base/reference/active_chart|ACTIVE]] , is similar to [[ref:libraries/base/reference/sequence_chart|SEQUENCE]] but describes infinite rather than finite sequences.
|
||||
|
||||
=Implementations=
|
||||
|
||||
@@ -285,22 +285,22 @@ as two categories with two subcategories each:
|
||||
* Linked implementations, which may be one-way or two-way.
|
||||
* Arrayed implementations, which may be resizable or fixed.
|
||||
|
||||
A linked implementation uses linked cells, each containing an item and a reference to the next cell. One-way structures are described by classes whose names begin with LINKED_, for example [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . Two-way structures use cells which, in addition to the reference to the next cell, also include a reference to the previous one. Their names begin with TWO_WAY_. <br/>
|
||||
A linked implementation uses linked cells, each containing an item and a reference to the next cell. One-way structures are described by classes whose names begin with LINKED_, for example [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . Two-way structures use cells which, in addition to the reference to the next cell, also include a reference to the previous one. Their names begin with TWO_WAY_. <br/>
|
||||
An arrayed implementation uses an array to represent a linear structure. If the array is resizable, the corresponding class name begins with ARRAYED_, for example <br/>
|
||||
[[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] ; if not, the prefix is FIXED_.
|
||||
[[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] ; if not, the prefix is FIXED_.
|
||||
|
||||
==Linked structures==
|
||||
|
||||
A linked structure requires two classes: one, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , describes the list proper; the other, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , describes the individual list cells. The figure should help understand the difference; it describes a linked list, but the implementation of linked circular chains is similar.
|
||||
A linked structure requires two classes: one, such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , describes the list proper; the other, such as [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , describes the individual list cells. The figure should help understand the difference; it describes a linked list, but the implementation of linked circular chains is similar.
|
||||
|
||||
|
||||
[[Image:linked-list|fig.3: Linked list and linked cells]]
|
||||
|
||||
|
||||
The instance of type [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] shown at the top contains general information about the list, such as the number of items (<eiffel>count</eiffel>) and a reference to the first element (first). Because lists are active structures with a notion of current position, there is also a reference active to the cell at the current position. An entity declared as
|
||||
The instance of type [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] shown at the top contains general information about the list, such as the number of items (<eiffel>count</eiffel>) and a reference to the first element (first). Because lists are active structures with a notion of current position, there is also a reference active to the cell at the current position. An entity declared as
|
||||
<code>my_list: LINKED_LIST [SOME_TYPE]</code>
|
||||
|
||||
will have as its run-time value (if not void) a reference to such an object, which is really a list header. The actual list content is given by the [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] instances, each of which contains a value of type <eiffel>SOME_TYPE</eiffel> and a reference to the next item, called <eiffel>right</eiffel>. <br/>
|
||||
will have as its run-time value (if not void) a reference to such an object, which is really a list header. The actual list content is given by the [[ref:libraries/base/reference/linkable_chart|LINKABLE]] instances, each of which contains a value of type <eiffel>SOME_TYPE</eiffel> and a reference to the next item, called <eiffel>right</eiffel>. <br/>
|
||||
Clearly, a header of type <code>LINKED_LIST [SOME_TYPE]</code> will be associated with cells of type <code>LINKABLE [SOME_TYPE]</code>. <br/>
|
||||
Features such as active and first are used only for the implementation; they are not exported, and so you will not find them in the flat-short specifications, although the figures show them to illustrate the representation technique. <br/>
|
||||
A similar implementation is used for two-way-linked structures such as two-way lists and two-way circular chains.
|
||||
@@ -311,14 +311,14 @@ A similar implementation is used for two-way-linked structures such as two-way l
|
||||
|
||||
==Linked cells==
|
||||
|
||||
The classes describing list cells are descendants of a deferred class called [[ref:/libraries/base/reference/cell_chart|CELL]] , whose features are:
|
||||
The classes describing list cells are descendants of a deferred class called [[ref:libraries/base/reference/cell_chart|CELL]] , whose features are:
|
||||
* <eiffel>item</eiffel>, the contents of the cell.
|
||||
* <eiffel>put </eiffel> <code>( v :</code> <code>like </code> <eiffel>item</eiffel> <code>)</code>, which replaces the contents of the cell by a new value.
|
||||
|
||||
Class [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] is an effective descendant of [[ref:/libraries/base/reference/cell_chart|CELL]] , used for one-way linked structures. It introduces features <eiffel>right</eiffel>, a reference to another cell to which the current <br/>
|
||||
cell will be linked. Two-way linked structures use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] , an heir of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] which to the above features adds <eiffel>left</eiffel>, a reference to the preceding cell in the structure.
|
||||
Class [[ref:libraries/base/reference/linkable_chart|LINKABLE]] is an effective descendant of [[ref:libraries/base/reference/cell_chart|CELL]] , used for one-way linked structures. It introduces features <eiffel>right</eiffel>, a reference to another cell to which the current <br/>
|
||||
cell will be linked. Two-way linked structures use [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] , an heir of [[ref:libraries/base/reference/linkable_chart|LINKABLE]] which to the above features adds <eiffel>left</eiffel>, a reference to the preceding cell in the structure.
|
||||
|
||||
{{caution|Do not confuse the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/cell_chart|CELL]] and its descendants, such as [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , with the <eiffel>item</eiffel> feature of the classes describing linear structures, such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . For a linked list, <eiffel>item</eiffel> returns the item at cursor position. }}
|
||||
{{caution|Do not confuse the <eiffel>item</eiffel> feature of [[ref:libraries/base/reference/cell_chart|CELL]] and its descendants, such as [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , with the <eiffel>item</eiffel> feature of the classes describing linear structures, such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . For a linked list, <eiffel>item</eiffel> returns the item at cursor position. }}
|
||||
|
||||
It may be implemented as
|
||||
<code>item: G is
|
||||
@@ -327,39 +327,39 @@ It may be implemented as
|
||||
Result := active.item
|
||||
end</code>
|
||||
|
||||
using the <eiffel>item</eiffel> feature of [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , applied to <eiffel>active</eiffel>.
|
||||
using the <eiffel>item</eiffel> feature of [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , applied to <eiffel>active</eiffel>.
|
||||
|
||||
==One-way and two-way linked chains==
|
||||
|
||||
If you look at the interfaces of one-way and two-way linked structures, you will notice that they are almost identical. This is because it is possible to implement features such as <eiffel>back</eiffel> for one-way structures such as described by [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linked_circular_chart|LINKED_CIRCULAR]] . A simple implementation of <eiffel>back</eiffel> stores away a reference to the current active item, executes <eiffel>start</eiffel>, and then performs <eiffel>forth</eiffel> until the item to the right of the cursor position is the previous <eiffel>active</eiffel>. <br/>
|
||||
If you look at the interfaces of one-way and two-way linked structures, you will notice that they are almost identical. This is because it is possible to implement features such as <eiffel>back</eiffel> for one-way structures such as described by [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:libraries/base/reference/linked_circular_chart|LINKED_CIRCULAR]] . A simple implementation of <eiffel>back</eiffel> stores away a reference to the current active item, executes <eiffel>start</eiffel>, and then performs <eiffel>forth</eiffel> until the item to the right of the cursor position is the previous <eiffel>active</eiffel>. <br/>
|
||||
Although correct, such an implementation is of course rather inefficient since it requires a traversal of the list. In terms of algorithmic complexity, it is in O (<eiffel>count</eiffel>), meaning that its execution time is on the average proportional to the number of items in the structure. In contrast, <eiffel>forth</eiffel> is O (1), that is to say, takes an execution time bounded by a constant.
|
||||
|
||||
{{caution|As a consequence, you should not use one-way linked structures if you need to execute more than occasional <eiffel>back</eiffel> operations (and other operations requiring access to previous items, such as <eiffel>remove_left</eiffel>). }}
|
||||
|
||||
Two-way linked structures, such as those described by [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] , treat the two directions symmetrically, so that <eiffel>back</eiffel> will be just as efficient as <eiffel>forth</eiffel>. Hence the following important advice: If you need to traverse a linked structure both ways, not just left to right, use the <eiffel>TWO_WAY_</eiffel> classes, not the <eiffel>LINKED_</eiffel> versions. The <eiffel>TWO_WAY_</eiffel> structures will take up more space, since they use [[ref:/libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] rather than [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] cells, but for most applications this space penalty is justified by the considerable gains in time that will result if right-to-left operations are frequently needed.
|
||||
Two-way linked structures, such as those described by [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] , treat the two directions symmetrically, so that <eiffel>back</eiffel> will be just as efficient as <eiffel>forth</eiffel>. Hence the following important advice: If you need to traverse a linked structure both ways, not just left to right, use the <eiffel>TWO_WAY_</eiffel> classes, not the <eiffel>LINKED_</eiffel> versions. The <eiffel>TWO_WAY_</eiffel> structures will take up more space, since they use [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] rather than [[ref:libraries/base/reference/linkable_chart|LINKABLE]] cells, but for most applications this space penalty is justified by the considerable gains in time that will result if right-to-left operations are frequently needed.
|
||||
|
||||
==Arrayed chains==
|
||||
|
||||
Arrayed structures as described by [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] and [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] use arrays for their implementations. A list or circular chain of <eiffel>count</eiffel> items may be stored in positions 1 to <eiffel>count</eiffel> of an array of <eiffel>capacity</eiffel> items, where <eiffel>capacity</eiffel> >= <eiffel>count</eiffel>. <br/>
|
||||
An instance of [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] , as the name suggests, has a fixed number of items. In particular:
|
||||
* Query extendible has value false for [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] : you may replace existing items, but not add any, even at the end. A [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] is created with a certain number of items and retains that number.
|
||||
* As a result, [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] joins the deferred feature count of [[ref:/libraries/base/reference/list_chart|LIST]] with the feature count of ARRAY, which satisfies the property <eiffel>count</eiffel> = <eiffel>capacity</eiffel>.
|
||||
Arrayed structures as described by [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] and [[ref:libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] use arrays for their implementations. A list or circular chain of <eiffel>count</eiffel> items may be stored in positions 1 to <eiffel>count</eiffel> of an array of <eiffel>capacity</eiffel> items, where <eiffel>capacity</eiffel> >= <eiffel>count</eiffel>. <br/>
|
||||
An instance of [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] , as the name suggests, has a fixed number of items. In particular:
|
||||
* Query extendible has value false for [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] : you may replace existing items, but not add any, even at the end. A [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] is created with a certain number of items and retains that number.
|
||||
* As a result, [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] joins the deferred feature count of [[ref:libraries/base/reference/list_chart|LIST]] with the feature count of ARRAY, which satisfies the property <eiffel>count</eiffel> = <eiffel>capacity</eiffel>.
|
||||
* Query <eiffel>prunable </eiffel>has value false too: it is not possible to remove an item from a fixed list.
|
||||
|
||||
In contrast, [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] has almost the same interface as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] . In particular, it is possible to add items at the end using procedure <eiffel>extend</eiffel>; if the call causes the list to grow beyond the current array's capacity, it will trigger a resizing. This is achieved by using the procedure <eiffel>force</eiffel> of class ARRAY to implement <eiffel>extend</eiffel>. [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] even has the insertion procedures (<eiffel>put_front</eiffel>, <eiffel>put_left</eiffel>, <eiffel>put_right</eiffel>) and removal procedures (<eiffel>prune</eiffel>, <eiffel>remove</eiffel>, <eiffel>remove_left</eiffel>, <eiffel>remove_right</eiffel>) that apply to arbitrary positions and appear in the linked implementations. These procedures, however, are rather inefficient, since they usually require moving a whole set of array items, an O (count) operation. (Procedure <eiffel>extend</eiffel> does not suffer from this problem, since it is easy to add an item to the end of an array, especially if there is still room so that no resizing is necessary.)
|
||||
In contrast, [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] has almost the same interface as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] . In particular, it is possible to add items at the end using procedure <eiffel>extend</eiffel>; if the call causes the list to grow beyond the current array's capacity, it will trigger a resizing. This is achieved by using the procedure <eiffel>force</eiffel> of class ARRAY to implement <eiffel>extend</eiffel>. [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] even has the insertion procedures (<eiffel>put_front</eiffel>, <eiffel>put_left</eiffel>, <eiffel>put_right</eiffel>) and removal procedures (<eiffel>prune</eiffel>, <eiffel>remove</eiffel>, <eiffel>remove_left</eiffel>, <eiffel>remove_right</eiffel>) that apply to arbitrary positions and appear in the linked implementations. These procedures, however, are rather inefficient, since they usually require moving a whole set of array items, an O (count) operation. (Procedure <eiffel>extend</eiffel> does not suffer from this problem, since it is easy to add an item to the end of an array, especially if there is still room so that no resizing is necessary.)
|
||||
|
||||
{{caution|The situation of these features in [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] is similar to the situation of <eiffel>back</eiffel> in classes describing one-way linked structures: it is convenient to include them because they may be needed once in a while and an implementation exists; but using them more than occasionally may result in serious inefficiencies. If you do need to perform arbitrary insertions and removal, use linked structures, not arrayed ones. }}
|
||||
{{caution|The situation of these features in [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] is similar to the situation of <eiffel>back</eiffel> in classes describing one-way linked structures: it is convenient to include them because they may be needed once in a while and an implementation exists; but using them more than occasionally may result in serious inefficiencies. If you do need to perform arbitrary insertions and removal, use linked structures, not arrayed ones. }}
|
||||
|
||||
Arrayed structures, however, use up less space than linked representations. So they are appropriate for chains on which, except possibly for insertions at the end, few insertion and removal operations or none at all are expected after creation. [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] offers few advantages over [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] . [[ref:/libraries/base/reference/fixed_list_chart|FIXED_LIST]] may be useful, however, for cases in which the fixed number of items is part of the specification, and any attempt to add more items must be treated as an error. For circular chains only one variant is available, [[ref:/libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] , although writing a <eiffel>FIXED_</eiffel> version would be a simple exercise.
|
||||
Arrayed structures, however, use up less space than linked representations. So they are appropriate for chains on which, except possibly for insertions at the end, few insertion and removal operations or none at all are expected after creation. [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] offers few advantages over [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] . [[ref:libraries/base/reference/fixed_list_chart|FIXED_LIST]] may be useful, however, for cases in which the fixed number of items is part of the specification, and any attempt to add more items must be treated as an error. For circular chains only one variant is available, [[ref:libraries/base/reference/arrayed_circular_chart|ARRAYED_CIRCULAR]] , although writing a <eiffel>FIXED_</eiffel> version would be a simple exercise.
|
||||
|
||||
==Multi-arrayed lists==
|
||||
|
||||
For lists one more variant is available, combining some of the advantages of arrayed and linked implementations: [[ref:/libraries/base/reference/multi_array_list_chart|MULTI_ARRAY_LIST]] . With this implementation a list is <br/>
|
||||
For lists one more variant is available, combining some of the advantages of arrayed and linked implementations: [[ref:libraries/base/reference/multi_array_list_chart|MULTI_ARRAY_LIST]] . With this implementation a list is <br/>
|
||||
divided into a number of blocks. Each block is an array, but the successive arrays are linked.
|
||||
|
||||
=Sorted Linear Structures=
|
||||
|
||||
The class [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , an heir of [[ref:/libraries/base/reference/bilinear_chart|BILINEAR]] , is declared as
|
||||
The class [[ref:libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , an heir of [[ref:libraries/base/reference/bilinear_chart|BILINEAR]] , is declared as
|
||||
<code>deferred class
|
||||
COMPARABLE_STRUCT [G -> COMPARABLE]
|
||||
inherit
|
||||
@@ -372,13 +372,13 @@ As indicated by the constrained generic parameter it describes bilinear structur
|
||||
{{caution|The class name COMPARABLE_STRUCT, chosen for brevity's sake, is slightly misleading: it is not the structures that are comparable but their items. }}
|
||||
|
||||
COMPARABLE_STRUCT introduces the features <eiffel>min</eiffel> and <eiffel>max</eiffel>, giving access to the minimum and maximum elements of a structure; these are always present for a finite <br/>
|
||||
structure with a total order relation. [[ref:/libraries/base/reference/sorted_struct_chart|SORTED_STRUCT]] , an heir of [[ref:/libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , describes structures that can be sorted; it introduces the query sorted and the command sort. <br/>
|
||||
The deferred class [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] describes lists whose items are kept ordered in a way that is compatible with a partial order relation defined on them. The class is declared as
|
||||
structure with a total order relation. [[ref:libraries/base/reference/sorted_struct_chart|SORTED_STRUCT]] , an heir of [[ref:libraries/base/reference/comparable_struct_chart|COMPARABLE_STRUCT]] , describes structures that can be sorted; it introduces the query sorted and the command sort. <br/>
|
||||
The deferred class [[ref:libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] describes lists whose items are kept ordered in a way that is compatible with a partial order relation defined on them. The class is declared as
|
||||
<code>deferred class
|
||||
PART_SORTED_LIST [G -> COMPARABLE]...</code>
|
||||
|
||||
An implementation based on two-way linked lists is available through the effective heir [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] . <br/>
|
||||
The deferred class [[ref:/libraries/base/reference/sorted_list_chart|SORTED_LIST]] , which inherits from [[ref:/libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] , assumes that the order relation on G is a total order. As a result, the class is able to introduce features <eiffel>min</eiffel>, <eiffel>max</eiffel> and <eiffel>median</eiffel>. Here too a two-way linked list implementation is available, through the effective class [[ref:/libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] .
|
||||
An implementation based on two-way linked lists is available through the effective heir [[ref:libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] . <br/>
|
||||
The deferred class [[ref:libraries/base/reference/sorted_list_chart|SORTED_LIST]] , which inherits from [[ref:libraries/base/reference/part_sorted_list_chart|PART_SORTED_LIST]] , assumes that the order relation on G is a total order. As a result, the class is able to introduce features <eiffel>min</eiffel>, <eiffel>max</eiffel> and <eiffel>median</eiffel>. Here too a two-way linked list implementation is available, through the effective class [[ref:libraries/base/reference/sorted_two_way_list_chart|SORTED_TWO_WAY_LIST]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[[Property:uuid|4f65d62b-940b-c3c2-557e-d709a2a1bcaf]]
|
||||
A dispenser is called that way because of the image of a vending machine (a dispenser) of a rather primitive nature, in which there is only one button. If you press the button and the dispenser is not empty, you get one of its items in the exit tray at the bottom, but you do not choose that item: the machine does. There is also an input slot at the top, into which you may deposit new items; but you have no control over the order in which successive button press operations will retrieve these items.
|
||||
|
||||
The deferred class [[ref:/libraries/base/reference/dispenser_chart|DISPENSER]] provides the facilities which will be shared by all specialized classes. In fact, the interface of all dispenser classes is nearly identical, with the exception of a few extra possibilities offered by priority queues. Many kinds of dispenser are possible, each defined by the relation that the machine defines between the order in which items are inserted and the order in which they arereturned. The Base libraries support three important categories - stacks, queues, and priority queues:
|
||||
The deferred class [[ref:libraries/base/reference/dispenser_chart|DISPENSER]] provides the facilities which will be shared by all specialized classes. In fact, the interface of all dispenser classes is nearly identical, with the exception of a few extra possibilities offered by priority queues. Many kinds of dispenser are possible, each defined by the relation that the machine defines between the order in which items are inserted and the order in which they arereturned. The Base libraries support three important categories - stacks, queues, and priority queues:
|
||||
* A stack is a dispenser with a last-in, first-out (LIFO) internal policy: items come out in the reverse order of their insertion. Each button press returns the last deposited item.
|
||||
* A queue is a dispenser with a first-in, first-out (FIFO) internal policy: items come out in the order of their insertion. Each button press returns the oldest item deposited and not yet removed.
|
||||
* In a priority queue, items have an associated notion of order; the element that comes out at any given time is the largest of those which are in the dispenser.
|
||||
@@ -12,24 +12,24 @@ The deferred class [[ref:/libraries/base/reference/dispenser_chart|DISPENSER]]
|
||||
|
||||
Stacks - dispensers with a LIFO retrieval policy - are a ubiquitous structure in software development. Their most famous application is to parsing (syntactic analysis), but many other types of systems use one or more stacks. Class STACK describes general stacks, without commitment to a representation. This is a deferred class which may not be directly instantiated. The fundamental operations are put (add an element at end of queue), item (retrieve the oldest element, non-destructively), remove (remove the oldest element), is_empty (test for empty queue). <br/>
|
||||
Three effective heirs are provided:
|
||||
* [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] : stacks implemented as linked lists, with no limit on the number of items (<eiffel>count</eiffel>).
|
||||
* [[ref:/libraries/base/reference/bounded_stack_chart|BOUNDED_STACK]] : stacks implemented as arrays. For such stacks, the maximum number of items (<eiffel>capacity</eiffel>) is set at creation time.
|
||||
* [[ref:/libraries/base/reference/arrayed_stack_chart|ARRAYED_STACK]] : also implemented as arrays, but in this case there is no limit on the number of items; the interface is the same as [[ref:/libraries/base/reference/linked_stack_chart|LINKED_STACK]] except for the creation procedure. If the number of elements exceeds the initially allocated capacity, the array will simply be resized.
|
||||
* [[ref:libraries/base/reference/linked_stack_chart|LINKED_STACK]] : stacks implemented as linked lists, with no limit on the number of items (<eiffel>count</eiffel>).
|
||||
* [[ref:libraries/base/reference/bounded_stack_chart|BOUNDED_STACK]] : stacks implemented as arrays. For such stacks, the maximum number of items (<eiffel>capacity</eiffel>) is set at creation time.
|
||||
* [[ref:libraries/base/reference/arrayed_stack_chart|ARRAYED_STACK]] : also implemented as arrays, but in this case there is no limit on the number of items; the interface is the same as [[ref:libraries/base/reference/linked_stack_chart|LINKED_STACK]] except for the creation procedure. If the number of elements exceeds the initially allocated capacity, the array will simply be resized.
|
||||
|
||||
==Queues==
|
||||
|
||||
Class [[ref:/libraries/base/reference/queue_chart|QUEUE]] describes general queues, without commitment to a representation. This is a deferred class which may not be directly instantiated. Three non-deferred heirs are also provided, distinguished by the same properties as their stack counterparts:
|
||||
* [[ref:/libraries/base/reference/linked_queue_chart|LINKED_QUEUE]]
|
||||
* [[ref:/libraries/base/reference/bounded_queue_chart|BOUNDED_QUEUE]]
|
||||
* [[ref:/libraries/base/reference/arrayed_queue_chart|ARRAYED_QUEUE]]
|
||||
Class [[ref:libraries/base/reference/queue_chart|QUEUE]] describes general queues, without commitment to a representation. This is a deferred class which may not be directly instantiated. Three non-deferred heirs are also provided, distinguished by the same properties as their stack counterparts:
|
||||
* [[ref:libraries/base/reference/linked_queue_chart|LINKED_QUEUE]]
|
||||
* [[ref:libraries/base/reference/bounded_queue_chart|BOUNDED_QUEUE]]
|
||||
* [[ref:libraries/base/reference/arrayed_queue_chart|ARRAYED_QUEUE]]
|
||||
|
||||
==Priority Queues==
|
||||
|
||||
In a priority queue, each item has an associated priority value, and there is an order relation on these values. The item returned by item or removed by remove is the element with the highest priority.The most general class is [[ref:/libraries/base/reference/priority_queue_chart|PRIORITY_QUEUE]] , which is deferred. Two effective variants are provided:
|
||||
* [[ref:/libraries/base/reference/linked_priority_queue_chart|LINKED_PRIORITY_QUEUE]] , a linked list implementation.
|
||||
* [[ref:/libraries/base/reference/heap_priority_queue_chart|HEAP_PRIORITY_QUEUE]] which is more efficient and is to be preferred in most cases. A heap is organized like a binary tree, although physically stored in an array; elements with a high priority percolate towards the root.
|
||||
In a priority queue, each item has an associated priority value, and there is an order relation on these values. The item returned by item or removed by remove is the element with the highest priority.The most general class is [[ref:libraries/base/reference/priority_queue_chart|PRIORITY_QUEUE]] , which is deferred. Two effective variants are provided:
|
||||
* [[ref:libraries/base/reference/linked_priority_queue_chart|LINKED_PRIORITY_QUEUE]] , a linked list implementation.
|
||||
* [[ref:libraries/base/reference/heap_priority_queue_chart|HEAP_PRIORITY_QUEUE]] which is more efficient and is to be preferred in most cases. A heap is organized like a binary tree, although physically stored in an array; elements with a high priority percolate towards the root.
|
||||
|
||||
Because it must be possible to compare priorities, the type of the items must conform to [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] . Constrained genericity ensures this; all the priority queue classes have a formal generic parameter constrained by [[ref:/libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] .
|
||||
Because it must be possible to compare priorities, the type of the items must conform to [[ref:libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] . Constrained genericity ensures this; all the priority queue classes have a formal generic parameter constrained by [[ref:libraries/base/reference/part_comparable_chart|PART_COMPARABLE]] .
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ Here, given with its full implementation, is a typical Iteration library routine
|
||||
The precise form of the procedure in the class relies on a call to another procedure, until_continue, and on inherited assertions. Here everything has been unfolded for illustration purposes. <br/>
|
||||
This procedure will traverse the linear structure identified by target and apply the procedure calledaction on every item up to but excluding the first one satisfying test. <br/>
|
||||
The class similarly offers <eiffel>do_all</eiffel>, <eiffel>do_while</eiffel>, <eiffel>do_for</eiffel>, <eiffel>do_if</eiffel> and other procedures representing the common control structures. It also includes functions such as <eiffel>exists</eiffel> and <eiffel>forall</eiffel>, corresponding to the usual quantifiers. <br/>
|
||||
These iteration schemes depend on the procedure <eiffel>action</eiffel>, defining the action to be applied to successive elements, and on the function <eiffel>test</eiffel>, defining the boolean query to be applied to these elements. These features are declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] (the highest-level deferred class of the Iteration library); here is <eiffel>test</eiffel>:
|
||||
These iteration schemes depend on the procedure <eiffel>action</eiffel>, defining the action to be applied to successive elements, and on the function <eiffel>test</eiffel>, defining the boolean query to be applied to these elements. These features are declared in class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] (the highest-level deferred class of the Iteration library); here is <eiffel>test</eiffel>:
|
||||
<code>
|
||||
test: BOOLEAN
|
||||
-- Test to be applied to item at current position in
|
||||
@@ -96,12 +96,12 @@ These iteration schemes depend on the procedure <eiffel>action</eiffel>, definin
|
||||
not_off: not target.off
|
||||
end</code>
|
||||
|
||||
This indicates that the value of the boolean function <eiffel>test</eiffel> will be obtained by applying <eiffel>item_test</eiffel> to the item at the current position in the target structure. In [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , function <eiffel>item_test</eiffel> always return ; descendant classes will redefine it so as to describe the desired test. Similarly, <eiffel>action</eiffel> is declared in class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] as a call to <eiffel>item_action</eiffel>. Descendants will redefine <eiffel>item_action</eiffel>, which as initially declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is a procedure with a null body. <br/>
|
||||
This indicates that the value of the boolean function <eiffel>test</eiffel> will be obtained by applying <eiffel>item_test</eiffel> to the item at the current position in the target structure. In [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , function <eiffel>item_test</eiffel> always return ; descendant classes will redefine it so as to describe the desired test. Similarly, <eiffel>action</eiffel> is declared in class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] as a call to <eiffel>item_action</eiffel>. Descendants will redefine <eiffel>item_action</eiffel>, which as initially declared in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] is a procedure with a null body. <br/>
|
||||
Going through <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel> provides an extra degree of flexibility. Normally the action and test performed at each step apply to <eiffel>target</eiffel> <code> . </code><eiffel>item></eiffel>, so that it suffices to redefine the <eiffel>item_features</eiffel>. This is the case with all examples studied in this chapter. In a more general setting, however, you might need to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves.
|
||||
|
||||
==An example use of iteration==
|
||||
|
||||
Here now is an example illustrating the use of these mechanisms. The result will enable us to resize all the paragraphs of a text up to the first one that has been modified - as we might need to do, in a text processing system, to process an interactive user request. Assume a class <eiffel>TEXT</eiffel> that describes lists of paragraphs with certain additional features. The example will also assume a class <eiffel>PARAGRAPH</eiffel> with a procedure <eiffel>resize</eiffel>, and a boolean-valued attribute <eiffel>modified</eiffel> which indicates whether a paragraph has been modified. Class <eiffel>TEXT</eiffel> inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and so is a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] :
|
||||
Here now is an example illustrating the use of these mechanisms. The result will enable us to resize all the paragraphs of a text up to the first one that has been modified - as we might need to do, in a text processing system, to process an interactive user request. Assume a class <eiffel>TEXT</eiffel> that describes lists of paragraphs with certain additional features. The example will also assume a class <eiffel>PARAGRAPH</eiffel> with a procedure <eiffel>resize</eiffel>, and a boolean-valued attribute <eiffel>modified</eiffel> which indicates whether a paragraph has been modified. Class <eiffel>TEXT</eiffel> inherits from [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and so is a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] :
|
||||
<code>
|
||||
class
|
||||
TEXT
|
||||
@@ -151,7 +151,7 @@ feature {NONE}
|
||||
end</code>
|
||||
|
||||
Thanks to the iteration mechanism, the procedure <eiffel>resize_paragraphs</eiffel> simply needs two procedure calls:
|
||||
* To set its argument <code>t</code> as the iteration target, it uses procedure <eiffel>set</eiffel>. (This procedure is from class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] which passes it on to all iterator classes.)
|
||||
* To set its argument <code>t</code> as the iteration target, it uses procedure <eiffel>set</eiffel>. (This procedure is from class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] which passes it on to all iterator classes.)
|
||||
* Then it simply calls <eiffel>until_do</eiffel> as defined above.
|
||||
|
||||
Procedure <eiffel>item_action</eiffel> is redefined to describe the operation to be performed on each successive element. Function <eiffel>item_test</eiffel> is redefined to describe the exit test. <br/>
|
||||
@@ -165,43 +165,43 @@ Let us now explore the classes of the Iteration library and the different ways o
|
||||
==Overview of the classes==
|
||||
|
||||
There are only four Iteration classes, whose simple inheritance structure appeared at the beginning of this chapter.
|
||||
* [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , a deferred class which describes the most general notion.
|
||||
* [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating over linear structures and chains.
|
||||
* [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] , a repeated heir of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating in either direction over a bilinear structure.
|
||||
* [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , for iterating over trees.
|
||||
* [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , a deferred class which describes the most general notion.
|
||||
* [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating over linear structures and chains.
|
||||
* [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] , a repeated heir of [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , for iterating in either direction over a bilinear structure.
|
||||
* [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , for iterating over trees.
|
||||
|
||||
As you will remember from the [[EiffelBase, Abstract Container Structures: The Taxonomy|presentation]] of the abstract overall taxonomy, the traversal hierarchy describes how data structures can be traversed; its most general class is [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]] . <br/>
|
||||
As you will remember from the [[EiffelBase, Abstract Container Structures: The Taxonomy|presentation]] of the abstract overall taxonomy, the traversal hierarchy describes how data structures can be traversed; its most general class is [[ref:libraries/base/reference/two_way_list_chart|TRAVERSABLE]] . <br/>
|
||||
Each one of the iterator classes is paired with a traversal class (or two in one case):
|
||||
|
||||
|
||||
{| border="1"
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/iterator_chart|ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TRAVERSABLE]]
|
||||
| [[ref:libraries/base/reference/iterator_chart|ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TRAVERSABLE]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/linear_chart|LINEAR]]
|
||||
| [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/linear_chart|LINEAR]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]]
|
||||
| [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] , [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]]
|
||||
| [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] , [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]]
|
||||
|-
|
||||
| [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]]
|
||||
| [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]]
|
||||
| [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]]
|
||||
| [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE]]
|
||||
|}
|
||||
|
||||
|
||||
Each iterator class relies on the corresponding traversal class to provide the features for traversing the corresponding data structures, such as <eiffel>start</eiffel>, <eiffel>forth</eiffel>, and <eiffel>exhausted</eiffel> for linear structures. <br/>
|
||||
Of course the data structure class used in connection with a given iterator class does not need to be the iterator's exact correspondent as given by the above table; it may be any one of its descendants. For example you may use [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] to iterate over data structures described not just by [[ref:/libraries/base/reference/linear_chart|LINEAR]] but also by such descendants as [[ref:/libraries/base/reference/list_chart|LIST]] , [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , or even [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] if you do not need the backward iteration features (for which you will have to use [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ).
|
||||
Of course the data structure class used in connection with a given iterator class does not need to be the iterator's exact correspondent as given by the above table; it may be any one of its descendants. For example you may use [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] to iterate over data structures described not just by [[ref:libraries/base/reference/linear_chart|LINEAR]] but also by such descendants as [[ref:libraries/base/reference/list_chart|LIST]] , [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , or even [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] if you do not need the backward iteration features (for which you will have to use [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] ).
|
||||
|
||||
==General iteration facilities==
|
||||
|
||||
Class [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] defines the features that apply to all forms of iterator. <br/>
|
||||
An iterator will always apply to a certain target structure. The target is introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] by the feature target: [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] [G] <br/>
|
||||
Both the iterator classes and the traversal classes are generic, with a formal generic parameter G. The actual generic parameters will be matched through the choice of iteration target: for a generic derivation of the form <eiffel>SOME_ITERATOR</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] the target can only be of type <eiffel>SOME_TRAVERSABLE</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] for the same <eiffel>ACTUAL_TYPE</eiffel>, where <eiffel>SOME_TRAVERSABLE</eiffel> is the traversal class matching <eiffel>SOME_ITERATOR</eiffel> according to the preceding table ([[ref:/libraries/base/reference/linear_chart|LINEAR]] for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] and so on), or one of its proper descendants. <br/>
|
||||
Each of the proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] redefines the type of target to the matching proper descendant of [[ref:/libraries/base/reference/traversable_chart|TRAVERSABLE]] , to cover more specific variants of the iteration target, For example in [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] the feature is redefined to be of type [[ref:/libraries/base/reference/linear_chart|LINEAR]] . [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] also introduces the procedure for selecting a target:
|
||||
Class [[ref:libraries/base/reference/iterator_chart|ITERATOR]] defines the features that apply to all forms of iterator. <br/>
|
||||
An iterator will always apply to a certain target structure. The target is introduced in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] by the feature target: [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] [G] <br/>
|
||||
Both the iterator classes and the traversal classes are generic, with a formal generic parameter G. The actual generic parameters will be matched through the choice of iteration target: for a generic derivation of the form <eiffel>SOME_ITERATOR</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] the target can only be of type <eiffel>SOME_TRAVERSABLE</eiffel> [<eiffel>ACTUAL_TYPE</eiffel>] for the same <eiffel>ACTUAL_TYPE</eiffel>, where <eiffel>SOME_TRAVERSABLE</eiffel> is the traversal class matching <eiffel>SOME_ITERATOR</eiffel> according to the preceding table ([[ref:libraries/base/reference/linear_chart|LINEAR]] for [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] and so on), or one of its proper descendants. <br/>
|
||||
Each of the proper descendants of [[ref:libraries/base/reference/iterator_chart|ITERATOR]] redefines the type of target to the matching proper descendant of [[ref:libraries/base/reference/traversable_chart|TRAVERSABLE]] , to cover more specific variants of the iteration target, For example in [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] the feature is redefined to be of type [[ref:libraries/base/reference/linear_chart|LINEAR]] . [[ref:libraries/base/reference/iterator_chart|ITERATOR]] also introduces the procedure for selecting a target:
|
||||
<code>
|
||||
set (s: like target)
|
||||
-- Make s the new target of iterations.
|
||||
@@ -214,7 +214,7 @@ Each of the proper descendants of [[ref:/libraries/base/reference/iterator_chart
|
||||
target /= Void
|
||||
end</code>
|
||||
|
||||
Next [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces the routines describing the elementary action and test that will be applied to items of the iteration targets:
|
||||
Next [[ref:libraries/base/reference/iterator_chart|ITERATOR]] introduces the routines describing the elementary action and test that will be applied to items of the iteration targets:
|
||||
<code>
|
||||
action
|
||||
-- Action to be applied to item at current position in
|
||||
@@ -248,8 +248,8 @@ Next [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces the r
|
||||
|
||||
These routines rely on two others, <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>, which both take an argument of type G, the formal generic parameter. The reason, already noted above, is that in a vast majority of cases the iterated action and test solely depend, at each step of the traversal, on the item (of type G) at the current position. To define an iteration process, then, it suffices to redefine<eiffel> item_action</eiffel> and <eiffel>item_test</eiffel> in a descendant of the appropriate iteration class. Only in complex cases will it be necessary to redefine <eiffel>action</eiffel> and <eiffel>test</eiffel> themselves. <br/>
|
||||
If you encounter such a case, note the caveat about action changing the target's structure. Understandably enough, an iterator that attempts to change the data structure while traversing it may engage in strange behavior. No such risk exists if you only redefine <eiffel>item_action</eiffel>, which may change the contents of items but not the structure itself. <br/>
|
||||
Another feature introduced in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] is the query <eiffel>invariant_value</eiffel>, describing invariant properties that must be ensured at the beginning of any iteration and preserved by every iteration step. As declared in [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] this query always returns true, but proper descendants can redefine it to describe more interesting invariant properties. <br/>
|
||||
Finally, [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] introduces in deferred form the general iteration routines applicable to all iteration variants. They include two queries corresponding to the quantifiers of first-order predicate calculus:
|
||||
Another feature introduced in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] is the query <eiffel>invariant_value</eiffel>, describing invariant properties that must be ensured at the beginning of any iteration and preserved by every iteration step. As declared in [[ref:libraries/base/reference/iterator_chart|ITERATOR]] this query always returns true, but proper descendants can redefine it to describe more interesting invariant properties. <br/>
|
||||
Finally, [[ref:libraries/base/reference/iterator_chart|ITERATOR]] introduces in deferred form the general iteration routines applicable to all iteration variants. They include two queries corresponding to the quantifiers of first-order predicate calculus:
|
||||
* <eiffel>for_all</eiffel> will return true if all items of the target structure satisfy test.
|
||||
* <eiffel>exists</eiffel> will return true if at least one item satisfies test.
|
||||
|
||||
@@ -260,12 +260,12 @@ The other routines are commands which will traverse the target structure and app
|
||||
* <eiffel>do_until</eiffel>, to all items up to and including the first one that satisfies test.
|
||||
* <eiffel>while_do</eiffel> and <eiffel>do_while</eiffel>, to all items up to the first one that does not satisfy test. (This can also be achieved with <eiffel>until_do</eiffel> or <eiffel>do_until </eiffel> by choosing the opposite test.)
|
||||
|
||||
All these features, and most of the other iteration features introduced in proper descendants of [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] and described next, have no argument. Information about the target of iteration comes from feature <eiffel>target</eiffel>, set by procedure <eiffel>set</eiffel>; information about what needs to be done for each item of the target structure comes from <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>.
|
||||
All these features, and most of the other iteration features introduced in proper descendants of [[ref:libraries/base/reference/iterator_chart|ITERATOR]] and described next, have no argument. Information about the target of iteration comes from feature <eiffel>target</eiffel>, set by procedure <eiffel>set</eiffel>; information about what needs to be done for each item of the target structure comes from <eiffel>item_action</eiffel> and <eiffel>item_test</eiffel>.
|
||||
|
||||
==Linear and chain iteration==
|
||||
|
||||
[[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , an effective class, refines the iteration mechanisms for cases in which the target is a linear structure, such as a list in any implementation or a circular chain. <br/>
|
||||
The class effects all the deferred features inherited from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , taking advantage of the linear traversal mechanisms present in the corresponding traversal class, [[ref:/libraries/base/reference/linear_chart|LINEAR]] . Here for example is the effecting of <eiffel>do_if</eiffel>:
|
||||
[[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , an effective class, refines the iteration mechanisms for cases in which the target is a linear structure, such as a list in any implementation or a circular chain. <br/>
|
||||
The class effects all the deferred features inherited from [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , taking advantage of the linear traversal mechanisms present in the corresponding traversal class, [[ref:libraries/base/reference/linear_chart|LINEAR]] . Here for example is the effecting of <eiffel>do_if</eiffel>:
|
||||
<code>
|
||||
do_if
|
||||
-- Apply action to every item of target satisfying
|
||||
@@ -285,7 +285,7 @@ The class effects all the deferred features inherited from [[ref:/libraries/base
|
||||
end
|
||||
end</code>
|
||||
|
||||
This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> which, together with <eiffel>off</eiffel>, have for convenience been carried over to [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] from their counterparts in [[ref:/libraries/base/reference/linear_chart|LINEAR]] , with feature declarations such as
|
||||
This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiffel> and <eiffel>exhausted</eiffel> which, together with <eiffel>off</eiffel>, have for convenience been carried over to [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] from their counterparts in [[ref:libraries/base/reference/linear_chart|LINEAR]] , with feature declarations such as
|
||||
<code>
|
||||
off: BOOLEAN
|
||||
-- Is position of target off?
|
||||
@@ -296,18 +296,18 @@ This routine text relies on features <eiffel>start</eiffel>, <eiffel>forth</eiff
|
||||
end</code>
|
||||
|
||||
and similarly for the others. <br/>
|
||||
In addition to effecting the general iteration features from [[ref:/libraries/base/reference/iterator_chart|ITERATOR]] , class [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] introduces iteration features that apply to the specific case of linear structures:
|
||||
In addition to effecting the general iteration features from [[ref:libraries/base/reference/iterator_chart|ITERATOR]] , class [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] introduces iteration features that apply to the specific case of linear structures:
|
||||
* <eiffel>search (b :BOOLEAN)</eiffel> moves the iteration to the first position satisfying test if <code>b</code> is true, or not satisfying test if <code>b</code> is false. This use of a boolean argument to switch between two opposite semantics is not part of the recommended style, and you will find few if any other examples in the Base libraries. Here, however, it was deemed preferable to the alternative, which would have involved four separate procedures (if together with <eiffel>search</eiffel> we consider <eiffel>continue_search</eiffel> discussed next).
|
||||
* With a linear structure we can implement an iteration corresponding to the 'for' loop of traditional programming languages, defined by three integers: the starting position, the number of items to be traversed, and the step between consecutive items. This is provided by procedure <eiffel>do_for</eiffel> <code> ( starting , number , step :INTEGER). </code>
|
||||
* Since with a linear target the iterator can advance the cursor step by step, the basic iteration operations are complemented by variants which pick up from the position reached by the last call: <eiffel>continue_until</eiffel>, <eiffel>until_continue</eiffel>, <eiffel>continue_while</eiffel>, <eiffel>while_continue</eiffel>, <eiffel>continue_search</eiffel>, <eiffel>continue_for</eiffel>.
|
||||
|
||||
==Two-way iteration==
|
||||
|
||||
Class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] has all the features of [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , to which it adds features for iterating backward as well as forward. <br/>
|
||||
Class [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] has all the features of [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , to which it adds features for iterating backward as well as forward. <br/>
|
||||
The class introduces commands <eiffel>finish</eiffel> and <eiffel>back</eiffel>, applying the corresponding operations to the two-way target. It also has a backward variant for every iteration feature. The name of each such variant is the name of the forward feature followed by ''_back'': <eiffel>do_all_back</eiffel>, <eiffel>until_do_back</eiffel> and so on. <br/>
|
||||
An alternative design would have kept just one set of features and added two features: a command reverse to reverse the direction of future iteration operations, and a query backward to find out the direction currently in force. <br/>
|
||||
Contrary to what one might at first imagine, class [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] is extremely short and simple; its <code> Feature </code> clause only contains the declarations of two features, <eiffel>finish</eiffel> and <eiffel>back</eiffel>. <br/>
|
||||
The trick is to use repeated inheritance. [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] inherits twice from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] ; the first inheritance branch yields the forward iteration features, the second yields those for backward iteration. There is no need for any explicit declaration or redeclaration of iteration features. Here is the entire class text that yields this result:
|
||||
Contrary to what one might at first imagine, class [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] is extremely short and simple; its <code> Feature </code> clause only contains the declarations of two features, <eiffel>finish</eiffel> and <eiffel>back</eiffel>. <br/>
|
||||
The trick is to use repeated inheritance. [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] inherits twice from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] ; the first inheritance branch yields the forward iteration features, the second yields those for backward iteration. There is no need for any explicit declaration or redeclaration of iteration features. Here is the entire class text that yields this result:
|
||||
<code>
|
||||
class
|
||||
TWO_WAY_CHAIN_ITERATOR [G]
|
||||
@@ -379,13 +379,13 @@ This class provides a good example of the economy of expression that the full in
|
||||
|
||||
==Tree iteration==
|
||||
|
||||
Tree iterations, provided by class [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , work on trees of the cursor tree form; only with this form of tree are traversal operations possible. Three forms of iteration are provided: preorder, postorder and breadth-first. They correspond to the three traversal policies described in the discussion of trees. Here too it would seem that a rather lengthy class is needed, but repeated inheritance works wonders. <br/>
|
||||
[[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] simply inherits three times from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , renaming the features appropriately in each case:
|
||||
Tree iterations, provided by class [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] , work on trees of the cursor tree form; only with this form of tree are traversal operations possible. Three forms of iteration are provided: preorder, postorder and breadth-first. They correspond to the three traversal policies described in the discussion of trees. Here too it would seem that a rather lengthy class is needed, but repeated inheritance works wonders. <br/>
|
||||
[[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] simply inherits three times from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] , renaming the features appropriately in each case:
|
||||
* <eiffel>pre_do_all</eiffel>, <eiffel>pre_until</eiffel>, and so on.
|
||||
* <eiffel>post_do_all</eiffel>, <eiffel>post_until</eiffel>, and so on.
|
||||
* <eiffel>breadth_do_all</eiffel>, <eiffel>breadth_until</eiffel>, and so on.
|
||||
|
||||
All it needs to do then is to redefine the type of target to be [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE [G]]] , and to redefine six features: the three renamed start (<eiffel>pre_start</eiffel>, etc.) and the three forth ( <eiffel>pre_ forth</eiffel>, and so on). These seven redefinitions give us a full-fledged battery of tree iteration mechanisms.
|
||||
All it needs to do then is to redefine the type of target to be [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE [G]]] , and to redefine six features: the three renamed start (<eiffel>pre_start</eiffel>, etc.) and the three forth ( <eiffel>pre_ forth</eiffel>, and so on). These seven redefinitions give us a full-fledged battery of tree iteration mechanisms.
|
||||
|
||||
=Building and Using Iterators=
|
||||
|
||||
@@ -394,14 +394,14 @@ An application class may use one of the iteration classes in either of two ways:
|
||||
|
||||
==The single descendant technique==
|
||||
|
||||
Assume an application class <eiffel>PROCESSOR</eiffel> that is a proper descendant of one of the effective iteration classes studied in this chapter. Then a routine of <eiffel>PROCESSOR</eiffel>, say <eiffel>iterate</eiffel>, may iterate a certain action over a data structure, subject to a certain test. First, class <eiffel>PROCESSOR</eiffel> must specify the action by redefining item_action and item_test (or, in the most general case, action and test). Then routine iterate must specify the target data structure through a call of the form <code>set (t)</code> where t represents the selected target data structure. The type of t must correspond to the iteration class selected as ancestor of <eiffel>PROCESSOR</eiffel>: for [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|LINEAR]] (such as [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:/libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , LINKED_CIRCULAR or any other list or circular chain classes); for [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/linear_chart|BILINEAR]] such as [[ref:/libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] or [[ref:/libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] ; for [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] it must be a descendant of [[ref:/libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] . In all cases the actual generic parameters of the iterator class and ofthe data structure class must be compatible. Then the iteration proper is obtained simply by calling the appropriate procedure, without any qualification or arguments, for example: do_ if <br/>
|
||||
Assume an application class <eiffel>PROCESSOR</eiffel> that is a proper descendant of one of the effective iteration classes studied in this chapter. Then a routine of <eiffel>PROCESSOR</eiffel>, say <eiffel>iterate</eiffel>, may iterate a certain action over a data structure, subject to a certain test. First, class <eiffel>PROCESSOR</eiffel> must specify the action by redefining item_action and item_test (or, in the most general case, action and test). Then routine iterate must specify the target data structure through a call of the form <code>set (t)</code> where t represents the selected target data structure. The type of t must correspond to the iteration class selected as ancestor of <eiffel>PROCESSOR</eiffel>: for [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/linear_chart|LINEAR]] (such as [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] , [[ref:libraries/base/reference/arrayed_list_chart|ARRAYED_LIST]] , LINKED_CIRCULAR or any other list or circular chain classes); for [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/linear_chart|BILINEAR]] such as [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] or [[ref:libraries/base/reference/two_way_circular_chart|TWO_WAY_CIRCULAR]] ; for [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] it must be a descendant of [[ref:libraries/base/reference/cursor_tree_chart|CURSOR_TREE]] . In all cases the actual generic parameters of the iterator class and ofthe data structure class must be compatible. Then the iteration proper is obtained simply by calling the appropriate procedure, without any qualification or arguments, for example: do_ if <br/>
|
||||
It is hard to imagine a simpler scheme: no loops, no initialization, no arguments. Feature item_action may need to rely on some variable values. Because it does not take any argument, such values will have to be treated as attributes, with the corresponding <eiffel>set_...</eiffel> procedures to set and change their values. This also applies to the two schemes set next. <br/>
|
||||
The single descendant technique has one drawback: it provides the iterating class, <eiffel>PROCESSOR</eiffel>, with only one set of iteration particulars. This limitation does not affect the number of targets: you may use as many targets as you wish, as long as they are of compatible types, by calling a routine such as iterate several times, or calling several such routines, each call being preceded by a call to set to define a new target. The limitation also does not affect the iterating scheme: one iteration could use do_if, the next do_all and so on. But it does require the action and test to be the same in all cases. <br/>
|
||||
The next two techniques will remove this limitation.
|
||||
|
||||
==Using repeated inheritance==
|
||||
|
||||
One way to obtain several iteration schemes is a simple extension to the single descendant technique. You can use repeated inheritance to provide two or more variants. We have in fact already encountered the technique when studying how to derive [[ref:/libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] and [[ref:/libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] from [[ref:/libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] . The general pattern, applied here to just two iteration schemes but easily generalized to more, is straightforward:
|
||||
One way to obtain several iteration schemes is a simple extension to the single descendant technique. You can use repeated inheritance to provide two or more variants. We have in fact already encountered the technique when studying how to derive [[ref:libraries/base/reference/two_way_chain_iterator_chart|TWO_WAY_CHAIN_ITERATOR]] and [[ref:libraries/base/reference/cursor_tree_iterator_chart|CURSOR_TREE_ITERATOR]] from [[ref:libraries/base/reference/linear_iterator_chart|LINEAR_ITERATOR]] . The general pattern, applied here to just two iteration schemes but easily generalized to more, is straightforward:
|
||||
<code>
|
||||
class
|
||||
DUAL_PROCESSOR
|
||||
|
||||
@@ -27,16 +27,16 @@ With good implementations, however, it is possible to use hash tables with a per
|
||||
x := h.item (k)</code>
|
||||
|
||||
where <eiffel>h</eiffel> is a hash-table and <eiffel>k</eiffel> is a key (for example a string) as conceptually equivalent to the array operations mentioned above. <br/>
|
||||
The quality of a hashed implementation will depend both on the data structure that will store the objects, and on the choice of hashing function. Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] attempts to address the first concern; for the second, client developers will be responsible for choosing the proper hashing function, although Base provides a few predefined functions, in particular for class [[ref:/libraries/base/reference/string_8_chart|STRING]] .
|
||||
The quality of a hashed implementation will depend both on the data structure that will store the objects, and on the choice of hashing function. Class [[ref:libraries/base/reference/hash_table_chart|HASH_TABLE]] attempts to address the first concern; for the second, client developers will be responsible for choosing the proper hashing function, although Base provides a few predefined functions, in particular for class [[ref:libraries/base/reference/string_8_chart|STRING]] .
|
||||
|
||||
==When hash tables are appropriate==
|
||||
|
||||
You may keep objects in a hash table if for each one of these objects you can find a key that uniquely identifies it. The objects and their keys may be of many possible kinds:
|
||||
* '''H1'''. In a simple example, the objects are integers; each integer serves as its own key. (More precisely we will use its absolute value, since it is convenient to have non-negative keys only.) This case is of more than theoretical interest, since it makes hash tables appropriate for storing a set of integers with widely scattered values, for which simple array storage would be a waste of space (see requirement '''A3''' above).
|
||||
* '''H2'''. Frequently, the objects will be composite, that is to say, instances of a developer-defined class, and one of the attributes of that class, of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , can serve as the key. For example if you were writing an Eiffel compiler you would probably need to keep a data structure that includes information about classes of the system. Each class is represented by an object with several fields describing the properties of the class; one of these fields, the class name, corresponding to an attribute of type [[ref:/libraries/base/reference/string_8_chart|STRING]] , will serve as key.
|
||||
* '''H2'''. Frequently, the objects will be composite, that is to say, instances of a developer-defined class, and one of the attributes of that class, of type [[ref:libraries/base/reference/string_8_chart|STRING]] , can serve as the key. For example if you were writing an Eiffel compiler you would probably need to keep a data structure that includes information about classes of the system. Each class is represented by an object with several fields describing the properties of the class; one of these fields, the class name, corresponding to an attribute of type [[ref:libraries/base/reference/string_8_chart|STRING]] , will serve as key.
|
||||
* '''H3'''. Instead of being the full object (as in case '''H1''') or one of the object's fields (as in case '''H2'''), the key may have to be computed through a function of the generating class, which will take into account several attributes of the class (that is to say, for each object, several fields).
|
||||
|
||||
What this practically means is that in all cases you will need, in the generating class of the objects to be stored, a query (attribute or function) that gives the key. The type of the key is highly variable but must in all cases be a descendant of [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] . This is true of both [[ref:/libraries/base/reference/integer_32_chart|INTEGER]] (case '''H1''') and [[ref:/libraries/base/reference/string_8_chart|STRING]] (case '''H2'''). The requirements for being a [[ref:/libraries/base/reference/hashable_chart|HASHABLE]] are not harsh: all you need is a function hash_code that returns a non-negative integer.>
|
||||
What this practically means is that in all cases you will need, in the generating class of the objects to be stored, a query (attribute or function) that gives the key. The type of the key is highly variable but must in all cases be a descendant of [[ref:libraries/base/reference/hashable_chart|HASHABLE]] . This is true of both [[ref:libraries/base/reference/integer_32_chart|INTEGER]] (case '''H1''') and [[ref:libraries/base/reference/string_8_chart|STRING]] (case '''H2'''). The requirements for being a [[ref:libraries/base/reference/hashable_chart|HASHABLE]] are not harsh: all you need is a function hash_code that returns a non-negative integer.>
|
||||
|
||||
==Using hash tables==
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ This yields a simple definition of trees by multiple inheritance from [[ref:libr
|
||||
|
||||
===Dynamic recursive trees===
|
||||
|
||||
An example of dynamic tree structure is provided by class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , an heir of both [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] . There is also [[ref:libraries/base/reference/linked_tree_chart|LINKED_TREE]] , which inherits from [[ref:/libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:/libraries/base/reference/linkable_chart|LINKABLE]] , but [[ref:libraries/base/reference/two_way_tree_chart|TWO_WA Y_TREE]] is generally preferable since children of a node often needs to be traversed both ways; the notion of order is usually less significant here than for lists. Such a form of definition is a particularly effective way of conveying the profoundly recursive nature of trees. The corresponding classes are useful in many different areas such as graphics, text processing and compilation. To create a one-way or two-way linked tree, use
|
||||
An example of dynamic tree structure is provided by class [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] , an heir of both [[ref:libraries/base/reference/two_way_list_chart|TWO_WAY_LIST]] and [[ref:libraries/base/reference/bi_linkable_chart|BI_LINKABLE]] . There is also [[ref:libraries/base/reference/linked_tree_chart|LINKED_TREE]] , which inherits from [[ref:libraries/base/reference/linked_list_chart|LINKED_LIST]] and [[ref:libraries/base/reference/linkable_chart|LINKABLE]] , but [[ref:libraries/base/reference/two_way_tree_chart|TWO_WA Y_TREE]] is generally preferable since children of a node often needs to be traversed both ways; the notion of order is usually less significant here than for lists. Such a form of definition is a particularly effective way of conveying the profoundly recursive nature of trees. The corresponding classes are useful in many different areas such as graphics, text processing and compilation. To create a one-way or two-way linked tree, use
|
||||
<code>create my_tree.make (root_value)</code>
|
||||
|
||||
This will attach my_tree to a new one-node tree, with root_value at the root node. Here my_tree must be declared of type [[ref:libraries/base/reference/two_way_tree_chart|TWO_WAY_TREE]] [MY_TYPE] for some type MY_TYPE, and root_value must be of type MY_TYPE. <br/>
|
||||
@@ -100,7 +100,7 @@ Various procedures are available to move the cursor in all directions:
|
||||
* [[ref:libraries/base/reference/cursor_tree_chart|forth]] and [[ref:libraries/base/reference/cursor_tree_chart|back]] move the cursor forward and backward between siblings and can cause the cursor to end up [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] .
|
||||
* [[ref:libraries/base/reference/cursor_tree_chart|up]] moves the cursor up one level. The call may be made even when the cursor is [[ref:libraries/base/reference/cursor_tree_chart|after]] or [[ref:libraries/base/reference/cursor_tree_chart|before]] . If the cursor is on the root of the tree or below in an empty tree, the cursor ends up [[ref:libraries/base/reference/cursor_tree_chart|above]] .
|
||||
|
||||
You can move the cursor in any one direction ( [[ref:libraries/base/reference/cursor_tree_chart|up]] , [[ref:libraries/base/reference/cursor_tree_chart|down]] , [[ref:libraries/base/reference/cursor_tree_chart|forth]] , [[ref:libraries/base/reference/cursor_tree_chart|back]] ), repeatedly, until it is [[ref:libraries/base/reference/cursor_tree_chart|off]] ( [[ref:libraries/base/reference/cursor_tree_chart|above]] , [[ref:libraries/base/reference/cursor_tree_chart|below,]] [[ref:libraries/base/reference/cursor_tree_chart|after]] , [[ref:libraries/base/reference/cursor_tree_chart|before]] respectively), but once it is [[ref:libraries/base/reference/cursor_tree_chart|off]] , further movement in the same direction is prohibited. For example the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_left]] requires [[ref:libraries/base/reference/cursor_tree_chart|before]] to be false, and the precondition of [[ref:/libraries/base/reference/cursor_tree_chart|put_right]] requires [[ref:libraries/base/reference/cursor_tree_chart|after]] to be false. <br/>
|
||||
You can move the cursor in any one direction ( [[ref:libraries/base/reference/cursor_tree_chart|up]] , [[ref:libraries/base/reference/cursor_tree_chart|down]] , [[ref:libraries/base/reference/cursor_tree_chart|forth]] , [[ref:libraries/base/reference/cursor_tree_chart|back]] ), repeatedly, until it is [[ref:libraries/base/reference/cursor_tree_chart|off]] ( [[ref:libraries/base/reference/cursor_tree_chart|above]] , [[ref:libraries/base/reference/cursor_tree_chart|below,]] [[ref:libraries/base/reference/cursor_tree_chart|after]] , [[ref:libraries/base/reference/cursor_tree_chart|before]] respectively), but once it is [[ref:libraries/base/reference/cursor_tree_chart|off]] , further movement in the same direction is prohibited. For example the precondition of [[ref:libraries/base/reference/cursor_tree_chart|put_left]] requires [[ref:libraries/base/reference/cursor_tree_chart|before]] to be false, and the precondition of [[ref:libraries/base/reference/cursor_tree_chart|put_right]] requires [[ref:libraries/base/reference/cursor_tree_chart|after]] to be false. <br/>
|
||||
It is possible to move down from an [[ref:libraries/base/reference/cursor_tree_chart|above]] position; in an empty tree this brings the cursor [[ref:libraries/base/reference/cursor_tree_chart|below]] . Similarly, it is possible to move up from [[ref:libraries/base/reference/cursor_tree_chart|below]] , left from [[ref:libraries/base/reference/cursor_tree_chart|after]] , right from [[ref:libraries/base/reference/cursor_tree_chart|before]] . <br/>
|
||||
The sentinel element above the tree's root is considered to be the root of a forest containing just one tree. This view justifies the convention for the result of arity when the cursor is above: 0 if the tree [[ref:libraries/base/reference/cursor_tree_chart|is_empty]] , 1 if it has a root (viewed as the child of the fictitious sentinel element).
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ The support cluster offers some commonly needed functionality that do not belong
|
||||
|
||||
==Conversions, mathematical properties and ASCII characters==
|
||||
|
||||
A few utility classes complement the [[EiffelBase, The Kernel|kernel]] facilities. [[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are part of the data structure taxonomy; the others are meant to be used as ancestors by classes needing their features.
|
||||
A few utility classes complement the [[EiffelBase, The Kernel|kernel]] facilities. [[ref:libraries/base/reference/primes_chart|PRIMES]] , [[ref:libraries/base/reference/random_chart|RANDOM]] and [[ref:libraries/base/reference/fibonacci_chart|FIBONACCI]] are part of the data structure taxonomy; the others are meant to be used as ancestors by classes needing their features.
|
||||
|
||||
Two classes provide basic mathematical functions such as logarithms and trigonometric functions: [[ref:/libraries/base/reference/single_math_chart|SINGLE_MATH]] for single precision and [[ref:/libraries/base/reference/double_math_chart|DOUBLE_MATH]] for the double-precision variants. [[ref:/libraries/base/reference/math_const_chart|MATH_CONST]] contains mathematical constants: <code> p </code>, the square root of two, Euler's constant <code> e </code>.
|
||||
Two classes provide basic mathematical functions such as logarithms and trigonometric functions: [[ref:libraries/base/reference/single_math_chart|SINGLE_MATH]] for single precision and [[ref:libraries/base/reference/double_math_chart|DOUBLE_MATH]] for the double-precision variants. [[ref:libraries/base/reference/math_const_chart|MATH_CONST]] contains mathematical constants: <code> p </code>, the square root of two, Euler's constant <code> e </code>.
|
||||
|
||||
[[ref:/libraries/base/reference/primes_chart|PRIMES]] , [[ref:/libraries/base/reference/random_chart|RANDOM]] and [[ref:/libraries/base/reference/fibonacci_chart|FIBONACCI]] are data structure classes - heirs of [[ref:/libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] . In all of these classes function i_th takes an integer argument <code> i </code> and will return the i-th element of the sequence under consideration - prime numbers, pseudo-random numbers or Fibonacci numbers. These sequences are active structures, on which forth will advance the current position and item will return the value at the current position. A few other features are specific to each case: for example [[ref:/libraries/base/reference/random_flatshort|higher_prime]] will yield the smallest prime greater than or equal to a certain value, and [[ref:/libraries/base/reference/random_flatshort|set_seed]] will define the seed to be used for starting the pseudo-random sequence.
|
||||
[[ref:libraries/base/reference/primes_chart|PRIMES]] , [[ref:libraries/base/reference/random_chart|RANDOM]] and [[ref:libraries/base/reference/fibonacci_chart|FIBONACCI]] are data structure classes - heirs of [[ref:libraries/base/reference/countable_sequence_chart|COUNTABLE_SEQUENCE]] . In all of these classes function i_th takes an integer argument <code> i </code> and will return the i-th element of the sequence under consideration - prime numbers, pseudo-random numbers or Fibonacci numbers. These sequences are active structures, on which forth will advance the current position and item will return the value at the current position. A few other features are specific to each case: for example [[ref:libraries/base/reference/random_flatshort|higher_prime]] will yield the smallest prime greater than or equal to a certain value, and [[ref:libraries/base/reference/random_flatshort|set_seed]] will define the seed to be used for starting the pseudo-random sequence.
|
||||
|
||||
==Internal object structures==
|
||||
|
||||
Class [[ref:/libraries/base/reference/internal_chart|INTERNAL]] provides low-level access to internal object structures. It, too, is meant to be used as ancestor by classes needing its features. <br/>
|
||||
Class [[ref:libraries/base/reference/internal_chart|INTERNAL]] provides low-level access to internal object structures. It, too, is meant to be used as ancestor by classes needing its features. <br/>
|
||||
Here are some of the most useful calls and what they yield, <eiffel>obj</eiffel> being an entity attached to an object <eiffel>O</eiffel> and <eiffel>i</eiffel> an integer:
|
||||
* <eiffel>class_name (obj)</eiffel> : the name of the generator class for O.
|
||||
* <eiffel>dynamic_type (obj) </eiffel> : the integer code for the type of <eiffel>O</eiffel>, where each type in a system is identified by a unique code.
|
||||
@@ -24,7 +24,7 @@ Here are some of the most useful calls and what they yield, <eiffel>obj</eiffel>
|
||||
* <eiffel>yy_field (i, obj) </eiffel> where <eiffel>yy</eiffel> is boolean, character, integer, real or double: the value of the i-th field of <eiffel>O</eiffel>, if of the corresponding type; each declared of the appropriate type in the class.
|
||||
* <eiffel>is_special (obj) </eiffel> : a boolean query which indicates whether <eiffel>O</eiffel> is a special object (the sequence of values representing the elements of an array or the characters of a string).
|
||||
|
||||
{{warning|Only very special cases justify the use of the class [[ref:/libraries/base/reference/internal_chart|INTERNAL]]. Unless you are writing the lowest level of an interface between an Eiffel application and external tools (such as a database management system), and this requires passing to those tools information about the internals of Eiffel objects, you almost certainly should not use [[ref:/libraries/base/reference/internal_chart|INTERNAL]] . }}
|
||||
{{warning|Only very special cases justify the use of the class [[ref:libraries/base/reference/internal_chart|INTERNAL]]. Unless you are writing the lowest level of an interface between an Eiffel application and external tools (such as a database management system), and this requires passing to those tools information about the internals of Eiffel objects, you almost certainly should not use [[ref:libraries/base/reference/internal_chart|INTERNAL]] . }}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user