https://dev.eiffel.com/api.php?action=feedcontributions&user=Kenga&feedformat=atomEiffelStudio: an EiffelSoftware project - User contributions [en]2024-11-02T12:39:08ZUser contributionsMediaWiki 1.24.1https://dev.eiffel.com/index.php?title=EiffelBase2&diff=15154EiffelBase22014-04-30T11:04:53Z<p>Kenga: /* Iterators */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item) <br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class GUI_APPLICATION<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
-- Cars in the city and their graphical views.<br />
<br />
escape_police (c: CAR)<br />
-- Drive `c' away, repaint it and update its view.<br />
require<br />
car_in_city: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [https://bitbucket.org/nadiapolikarpova/traffic https://bitbucket.org/nadiapolikarpova/traffic]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14512EiffelBase22012-06-27T13:22:34Z<p>Kenga: /* Status and roadmap */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class GUI_APPLICATION<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
-- Cars in the city and their graphical views.<br />
<br />
escape_police (c: CAR)<br />
-- Drive `c' away, repaint it and update its view.<br />
require<br />
car_in_city: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [https://bitbucket.org/nadiapolikarpova/traffic https://bitbucket.org/nadiapolikarpova/traffic]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14405EiffelBase22012-04-11T14:19:29Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class GUI_APPLICATION<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
-- Cars in the city and their graphical views.<br />
<br />
escape_police (c: CAR)<br />
-- Drive `c' away, repaint it and update its view.<br />
require<br />
car_in_city: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14404EiffelBase22012-04-11T14:18:59Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class GUI_APPLICATION<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
-- Cars in the city and their graphical views.<br />
<br />
escape_police (c: CAR)<br />
-- Drive `c' away, repaint it and update its view.<br />
require<br />
car_on_map: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14403EiffelBase22012-04-11T14:16:49Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class GUI_APPLICATION<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
<br />
escape_police (c: CAR)<br />
require<br />
car_on_map: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14402EiffelBase22012-04-11T14:14:25Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERENCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class MAP<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
<br />
escape_police (c: CAR)<br />
require<br />
car_on_map: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14401EiffelBase22012-04-11T13:34:40Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
Sometimes you want to use an object as a key in a table,<br />
but the content of the object can change, so you cannot derive a hash code (or order) from any of its attributes.<br />
EiffelBase2 provides a utility class <e>V_REFERNCE_HASHABLE</e>,<br />
which derives a hash code from the object's identity rather than its content.<br />
For example:<br />
<e><br />
class <br />
CAR<br />
inherit <br />
V_REFERENCE_HASHABLE<br />
<br />
feature -- Access<br />
color: COLOR<br />
<br />
location: POINT<br />
<br />
feature -- Modification<br />
...<br />
end<br />
<br />
<br />
class MAP<br />
<br />
feature<br />
cars: V_HASH_TABLE [CAR, CAR_VIEW]<br />
<br />
escape_police (c: CAR)<br />
require<br />
car_on_map: cars.has_key (c)<br />
do<br />
c.move (100, 100) -- change location<br />
c.repaint (white) -- change color<br />
cars [c].update -- ... but still can be used to access its view<br />
end<br />
end<br />
</e><br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14385EiffelBase22012-04-05T15:33:31Z<p>Kenga: /* Inheritance */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, look at <e>V_SET</e>, which inherits directly from <e>V_CONTAINER</e>:<br />
<e><br />
note<br />
model: bag<br />
class V_CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: set<br />
class V_SET[G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain |=| set<br />
bag_definition: bag.is_constant (1)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>V_SET</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>set</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14384EiffelBase22012-04-05T15:29:03Z<p>Kenga: /* Status and roadmap */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14383EiffelBase22012-04-05T15:27:38Z<p>Kenga: /* Models */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
target: V_LIST<br />
-- List to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
<br />
Here we declared the model of class <e>V_LIST_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_LIST</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14382EiffelBase22012-04-05T15:26:05Z<p>Kenga: /* Contracts */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
class V_ITERATOR [G]<br />
feature -- Access<br />
<br />
target: V_CONTAINER<br />
-- Container to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
Here we declared the model of class <e>V_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_CONTAINER</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of regular features in their terms. <br />
For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. <br />
For commands we define their effects on the model queries of <e>Current</e> and the arguments.<br />
We also supply them with <e>modify</e> clauses that list all the model queries whose values are allowed to be changed by the command.<br />
These clauses can be used by tools to generate additional postconditions <e>m = old m</e> <br />
for each model query <e>m</e> of <e>Current</e> and other arguments that is not mentioned in the <e>modify</e> clause.<br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: <br />
it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>V_LIST_ITERATOR</e> shown above:<br />
<e><br />
note<br />
model: target, sequence, index<br />
<br />
class V_LIST_ITERATOR [G]<br />
<br />
feature -- Access<br />
<br />
item: G<br />
-- Item at current position.<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
<br />
off: BOOLEAN<br />
-- Is current position off scope?<br />
deferred<br />
ensure<br />
definition: Result = not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Extension<br />
<br />
extend_right (v: G)<br />
-- Insert `v' to the right of current position.<br />
-- Do not move cursor.<br />
note<br />
modify: sequence<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index) & v + sequence.tail (index + 1))<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14381EiffelBase22012-04-05T14:38:51Z<p>Kenga: /* Models */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence of elements is a model for a stack or a queue. <br />
A triple consisting of a reference to the target container, the sequence of elements and an integer is a model for an iterator.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: target, sequence, index<br />
class V_ITERATOR [G]<br />
feature -- Access<br />
<br />
target: V_CONTAINER<br />
-- Container to iterate over.<br />
deferred<br />
end<br />
<br />
index: INTEGER<br />
-- Current position.<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of elements in `target'.<br />
note<br />
status: specification<br />
deferred<br />
end<br />
end<br />
</e><br />
Here we declared the model of class <e>V_ITERATOR</e> consisting of tree components: <br />
a reference (to <e>V_CONTAINER</e>), a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. <br />
As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); <br />
regular queries meant to be called from the code can be also reused as model queries (as <e>target</e> and <e>index</e> in this example). <br />
We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
Those annotations can be used by tools to check, if a specification-only feature accidentally got called from non-specification code,<br />
and to remove such features from the code before compiling it.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14380EiffelBase22012-04-05T14:26:49Z<p>Kenga: /* Usage examples */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Immutable interfaces===<br />
With immutable interfaces you can give your clients read-only access to a container you store:<br />
<e><br />
class TRAM_LINE<br />
<br />
feature -- Access<br />
<br />
stations: V_SEQUENCE [STATION]<br />
-- Stations on the line.<br />
-- (Clients can traverse the stations, but cannot replace them, remove or add new ones.)<br />
do<br />
Result := station_list<br />
end<br />
<br />
feature {NONE} -- Implementation<br />
<br />
station_list: V_LIST [STATION]<br />
-- List of line stations.<br />
end<br />
</e><br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14378EiffelBase22012-04-05T13:47:02Z<p>Kenga: /* Design */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. <br />
All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity.<br />
<br />
In the diagrams below asterisk and italics font indicates a <e>deferred</e> class.<br />
Lighter fill color indicates that the class provides an ''immutable'' interface to the data,<br />
in other words, it is impossible to modify the content of the container using this interface.<br />
<br />
[[Image:eb2_container.png|1000px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|1000px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_iterator.png&diff=14377File:Eb2 iterator.png2012-04-05T13:40:05Z<p>Kenga: uploaded a new version of "Image:Eb2 iterator.png": Iterator hierarchy of EiffelBase2</p>
<hr />
<div>Class diagram of the iterator classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_container.png&diff=14376File:Eb2 container.png2012-04-05T13:39:01Z<p>Kenga: uploaded a new version of "Image:Eb2 container.png": Container Hierarchy of EiffelBase2</p>
<hr />
<div>Class diagram of the container classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14375EiffelBase22012-04-05T13:37:30Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available from the repository: [https://bitbucket.org/nadiapolikarpova/eiffelbase2/ https://bitbucket.org/nadiapolikarpova/eiffelbase2/]<br />
<br />
The source code is divided into two clusters:<br />
<br />
* <e>structures</e> - Data Structures, the core of EiffelBase2. The rest of current document is about this cluster.<br />
<br />
* <e>mml</e> - Mathematical Model Library: a library of immutable classes used in ''model-based contracts'' (see below).<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and ''streams''. A container is a finite storage of values, while a stream provides linear access to a set of values. A stream is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies: containers and streams/iterators. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
do<br />
across<br />
container as i<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
The same thing using the explicit syntax:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_cursor<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.new_cursor.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.new_cursor.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.new_cursor)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
It has been used in the following projects:<br />
* Traffic 4: modeling public transportation in a city [http://traffic.origo.ethz.ch/ http://traffic.origo.ethz.ch/]</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14101EiffelBase22011-05-02T13:16:48Z<p>Kenga: /* ToDo list */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
You can download a stable release of EiffelBase2 from the downloads page: [http://eiffelbase2.origo.ethz.ch/download http://eiffelbase2.origo.ethz.ch/download]<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''accessors''. A container is a finite storage of values. Accessors are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_INPUT_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_iterator<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.at_first.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.at_first.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.at_first)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add support for the <e>across</e> syntax.<br />
* Add more useful streams and iterators (for filtering, mapping, folding, extending lists).<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add files and directories.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14100EiffelBase22011-05-02T13:14:21Z<p>Kenga: /* Sets and tables */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
You can download a stable release of EiffelBase2 from the downloads page: [http://eiffelbase2.origo.ethz.ch/download http://eiffelbase2.origo.ethz.ch/download]<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''accessors''. A container is a finite storage of values. Accessors are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_INPUT_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_iterator<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple hash table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.at_first.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.at_first.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.at_first)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14099EiffelBase22011-05-02T13:13:58Z<p>Kenga: /* Download */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
You can download a stable release of EiffelBase2 from the downloads page: [http://eiffelbase2.origo.ethz.ch/download http://eiffelbase2.origo.ethz.ch/download]<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''accessors''. A container is a finite storage of values. Accessors are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_INPUT_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_iterator<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple has table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.at_first.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.at_first.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.at_first)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14079EiffelBase22011-03-21T18:59:39Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''accessors''. A container is a finite storage of values. Accessors are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Usage examples==<br />
<br />
===Iterators===<br />
Here is how you can iterate through any container:<br />
<e><br />
do_something (container: V_CONTAINER [INTEGER])<br />
local<br />
i: V_INPUT_ITERATOR [INTEGER]<br />
do<br />
from<br />
i := container.new_iterator<br />
until<br />
i.after<br />
loop<br />
print (i.item)<br />
i.forth<br />
end<br />
end<br />
</e><br />
<br />
Here is some more advanced stuff you can do with lists:<br />
<e><br />
do_something (list: V_LIST [INTEGER])<br />
local<br />
i: V_LIST_ITERATOR [INTEGER]<br />
do<br />
-- Find the last 0 at or before position 5:<br />
list.at (5).search_back (0)<br />
-- Find the first positive element at or after position 5:<br />
i := list.at (5)<br />
i.satisfy_forth (agent (x: INTEGER): BOOLEAN do Result := x > 0 end)<br />
-- And insert a 0 after it:<br />
i.extend_right (0)<br />
end<br />
</e><br />
<br />
===Sets and tables===<br />
<br />
Here is how you create and use a simple has table (keys must inherit from HASHABLE):<br />
<e><br />
do_something<br />
local<br />
table: V_HASH_TABLE [STRING, INTEGER]<br />
do<br />
create table.with_object_equality<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["cat"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
If you need a custom hash function or equivalence relation on keys, you can use V_GENERAL_HASH_TABLE, for example:<br />
<e><br />
do_something<br />
local<br />
table: V_GENERAL_HASH_TABLE [STRING, INTEGER]<br />
do<br />
-- Create case-insensitive table:<br />
create table.make (<br />
agent {STRING}.is_case_insensitive_equal,<br />
agent (s: STRING): INTEGER do Result := s.as_lower.hash_code end<br />
)<br />
table ["cat"] := 1<br />
table ["dog"] := 2<br />
print (table ["CAT"] + table ["dog"])<br />
-- Prints "3"<br />
end<br />
</e><br />
<br />
Similar style applies to <e>V_HASH_SET</e> and <e>V_GENERAL_HASH_SET</e>, <e>V_SORTED_TABLE</e> and <e>V_GENERAL_SORTED_TABLE</e>, <e>V_SORTED_SET</e> and <e>V_GENERAL_SORTED_SET</e>.<br />
<br />
===Stream piping===<br />
<br />
Iterators in EiffelBase2 are a special case of streams. Sometimes you can avoid writing a loop by piping an input stream into an output stream, for example:<br />
<e><br />
do_something<br />
local<br />
array: V_ARRAY [INTEGER]<br />
do<br />
create array.make (1, 10)<br />
-- Fill array with random integers:<br />
array.at_first.pipe (create {V_RANDOM})<br />
-- Fill array with values parsed from a string:<br />
array.at_first.pipe (create {V_STRING_INPUT [INTEGER]}.make ("1 2 3 4 5 6 7 8 9 10", agent {STRING}.to_integer))<br />
-- Print array elements into standard output:<br />
(create {V_STANDARD_OUTPUT}).pipe (array.at_first)<br />
-- Prints "1 2 3 4 5 6 7 8 9 10 "<br />
end<br />
</e><br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_container.png&diff=14078File:Eb2 container.png2011-03-21T17:48:26Z<p>Kenga: uploaded a new version of "Image:Eb2 container.png"</p>
<hr />
<div>Class diagram of the container classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14077EiffelBase22011-03-21T13:26:12Z<p>Kenga: /* Design */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''accessors''. A container is a finite storage of values. Accessors are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14075EiffelBase22011-03-11T12:44:21Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2 is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library, which has for many years played a central role in Eiffel development.<br />
<br />
==Download==<br />
<br />
The latest version of the EiffelBase2 source code is available in the repository: [https://svn.origo.ethz.ch/eiffelbase2/trunk/ https://svn.origo.ethz.ch/eiffelbase2/trunk/]<br />
<br />
==Goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Complete specifications. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
==Design==<br />
On the top level EiffelBase2 differentiates between ''containers'' and interfaces to access elements of containers, called ''observers''. A container is a finite storage of values. Observers are either ''maps'' (accessing elements by a unique key) or ''streams'' (linear access). An observer is not necessarily bound to a container, e.g. <e>RANDOM</e> stream observes an infinite sequence of pseudo-random numbers. Streams that traverse containers are called ''iterators''.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies. The first one is a hierarchy of containers and maps. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
EiffelBase2 is currently being developed as a project at ETH Zurich.<br />
<br />
===ToDo list===<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_iterator.png&diff=14074File:Eb2 iterator.png2011-03-10T14:19:30Z<p>Kenga: uploaded a new version of "Image:Eb2 iterator.png"</p>
<hr />
<div>Class diagram of the iterator classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_container.png&diff=14073File:Eb2 container.png2011-03-10T14:18:24Z<p>Kenga: uploaded a new version of "Image:Eb2 container.png"</p>
<hr />
<div>Class diagram of the container classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14072EiffelBase22011-03-10T14:16:42Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is related to the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Add immutable and mutable strings.<br />
* Make model class implementation more efficient.<br />
* Add classes and directories.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14012EiffelBase22010-11-21T13:43:44Z<p>Kenga: /* Comparison criteria */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is related to the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14011EiffelBase22010-11-21T13:43:09Z<p>Kenga: /* Comparison criteria */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is related the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=14010EiffelBase22010-11-21T13:31:36Z<p>Kenga: /* ToDo list */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13990EiffelBase22010-09-16T15:18:28Z<p>Kenga: /* ToDo list */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binary trees in pre- and postorder.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13989EiffelBase22010-09-16T15:17:48Z<p>Kenga: /* ToDo list */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13936EiffelBase22010-07-29T12:24:29Z<p>Kenga: /* ToDo list */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as opposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are too many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used in search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
An additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object's lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison criterion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrarily even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class defines a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define their effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
The model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in the model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly from <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>across</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13803EiffelBase22010-04-24T19:14:32Z<p>Kenga: /* Model-based contracts */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
===Models===<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
===Contracts===<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. Definitions of zero-argument queries, as usual, can be moved to the class invariant. For commands we define its effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
Model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space of the class.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
<br />
feature -- Access<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
...<br />
<br />
feature -- Status report<br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
...<br />
<br />
feature -- Element change<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
...<br />
<br />
invariant<br />
index_in_range: 0 <= index and index <= sequence.count + 1<br />
end<br />
</e><br />
<br />
===Inheritance===<br />
If a class <e>B</e> inherits from <e>A</e> it is free to choose, whether to reuse each of <e>A</e>'s model queries to represent its own model, as well as introduce new model queries. If <e>B</e> does not reuse an <e>A</e>'s model query is has to provide a ''linking invariant'': a definition of the old model query in terms of <e>B</e>'s model. Linking invariants explain the parent's model in terms of the heir's model and thus make sure that the inherited model-based contracts make sense in the heir.<br />
<br />
For example, suppose that <e>LIST</e> inherits directly fro <e>CONTAINER</e>, whose model is a bag:<br />
<e><br />
note<br />
model: bag<br />
class CONTAINER [G]<br />
...<br />
end<br />
<br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
...<br />
invariant<br />
...<br />
bag_domain_definition: bag.domain = sequence.range<br />
bag_definition: bag.domain.for all (agent (x: G): BOOLEAN<br />
do Result := bag [x] = sequence.occurrences (x) end)<br />
end<br />
</e><br />
Here the linking invariant, provided as part of the class invariant in <e>LIST</e> completely defines an old model query <e>bag</e> in terms of a new model query <e>sequence</e>.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13802EiffelBase22010-04-24T18:51:40Z<p>Kenga: /* Model-based contracts */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
-- Cursor position<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
-- Sequence of list elements<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
The purpose of introducing model queries is to define the postconditions of the regular features in their terms. For queries we define their result (or the model of the result, in case the query returns a fresh object) as a function of the model of <e>Current</e> and (the models of) the arguments. For commands we define its effects on the model queries of <e>Current</e> and the arguments. If a model query is not mentioned in the postcondition of a command, it is equivalent to stating that it's not modified. <br />
<br />
Model-based contracts approach does not constrain the way in which you write preconditions: it is not necessary to express them through model queries if they can be conveniently expressed otherwise.<br />
<br />
Class invariants in model-based contracts approach constrain the values of model queries to make them reflect precisely the abstract state space.<br />
<br />
Let us add a couple of features and model-based contracts into the class <e>LIST</e> shown above:<br />
<e><br />
off: BOOLEAN<br />
-- Is cursor off all elements?<br />
deferred<br />
ensure<br />
definition: not sequence.domain [index]<br />
end<br />
<br />
item: G<br />
-- Item at current position<br />
require<br />
not_off: not off<br />
deferred<br />
ensure<br />
definition: Result = sequence [index]<br />
end<br />
<br />
put_right (v: G)<br />
-- Put `v' to the right of the cursor<br />
require<br />
not_after: not after<br />
deferred<br />
ensure<br />
sequence_effect: sequence |=| old (sequence.front (index).extended (v) + sequence.tail (index + 1))<br />
index_effect: index = old index<br />
end<br />
</e><br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13801EiffelBase22010-04-24T18:29:16Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. All EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the current document for brevity. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13800EiffelBase22010-04-24T18:26:22Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e><ref>EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the document.</ref>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.<br />
<br />
<references/></div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13799EiffelBase22010-04-24T18:25:53Z<p>Kenga: /* Traversal mechanisms and classification criteria */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e><ref>EiffelBase2 class names start with <e>V_</e> (for ''Verified''), but the prefix is omitted in the document.</ref>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13798EiffelBase22010-04-24T18:18:54Z<p>Kenga: /* Model-based contracts */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The Mathematical Model Library (MML), which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <e>BOOLEAN</e> and <e>INTEGER</e>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
For example, a mathematical sequence is a model for a stack or a queue. A pair consisting of a sequence and an integer is a model for a list with an internal cursor.<br />
<br />
The value of each component of the model is defined by a ''model query''. You define the model of the class in the source code by listing its model queries under the tag <e>model</e> in the class's <e>note</e> clause. For example:<br />
<e><br />
note<br />
model: sequence, index<br />
class LIST [G]<br />
feature -- Access<br />
index: INTEGER<br />
deferred<br />
end<br />
...<br />
feature -- Specification<br />
sequence: MML_SEQUENCE [G]<br />
note<br />
status: specification<br />
...<br />
end<br />
</e><br />
Here we declared the model of class <e>LIST</e> consisting of two components: a mathematical sequence of type <e>MML_SEQUENCE</e> and an integer index. As you can see, model queries are not necessarily introduced specifically for specification purposes (as is the case with <e>sequence</e>); regular queries meant to be called from the code can be also reused as model queries (as <e>index</e> in this example). We attach a <e>status: specification</e> note to a query to indicate that its primary purpose is specification.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13797EiffelBase22010-04-24T17:58:38Z<p>Kenga: /* Model-based contracts */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
EiffelBase2 is specified using the ''model-based contracts'' specification method. This method prescribes that each class define a ''model'' - a mathematical object that represents explicitly its abstract state space. The model of a class is expressed as tuple of one or more predefined mathematical objects: booleans, integers, sets, relations, maps, sequences or bags. We also introduce a special mathematical sort for object IDs (references).<br />
<br />
Such mathematical objects in the program are represented by ''model classes'', which are immutable and thus are straightforward translations of mathematical definitions. The MML library, which is a part of EiffelBase2 contains model classes for sets, relations, maps, sequences and bags. Boolean and integer components of models are represented by standard classes <c>BOOLEAN</c> and <c>INTEGER</c>. Finally, arbitrary reference classes can be used as model components to denote the mathematical sort of references.<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13795EiffelBase22010-04-23T16:17:49Z<p>Kenga: /* Indexing */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that indices of arrays, like those of other indexed data structures, always start at 1.<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13794EiffelBase22010-04-23T16:16:41Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
===Indexing===<br />
The current version of EiffelBase2 is using the same policy for indexing as the one used in the classic EiffelBase: indexing of lists (and iterators) always starts from 1, whereas for arrays the starting index can be set to an arbitrary value. However, during the code review in the Chair of Software Engineering (17.03.2010) is was decided that the possibility to start arrays from an arbitrary index is not crucial and is used very rarely, but complicates the API. Thus it will probably be changed in future so that array indexing, like in other indexed data structures, always starts at 1.<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13793EiffelBase22010-04-23T16:03:37Z<p>Kenga: /* Status and roadmap */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.<br />
<br />
===ToDo list===<br />
Below you can see a list of most important changes planned for EiffelBase2.<br />
* Test extensively with AutoTest.<br />
* Implement <e>HASH_SET</e> and <e>HASH_TABLE</e>.<br />
* Implement <e>PREORDER_ITERATOR</e> and <e>POSTORDER_ITERATOR</e> to traverse binaries in pre- and postorder.<br />
* Iterator management: currently the situation when a container is modified through one iterator while it's being traversed with another is not handled anyhow.<br />
* Finish the implementation of the MML library.<br />
* Rewrite loops using the <e>accross</e> where appropriate.<br />
* Implement <e>RANDOM</e> and <e>STANDARD_INPUT</e> streams.<br />
* Add an iterator over keys for <e>TABLE</e>.<br />
* Make the library void-safe.<br />
* Implement more efficient data structures: e.g., tables with fast lookup both ways, heaps, skip lists, treaps, etc.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13792EiffelBase22010-04-23T14:48:09Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
===Traversal mechanisms and classification criteria===<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal access mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like <e>RANDOM</e> it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from <e>CONTAINER</e>. There is one exception: <e>SEQUENCE</e>, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
===Comparison criteria===<br />
Another important design decision for a data structures library is how to represent and modify comparison criteria for container elements.<br />
Adjustable comparison criterion is used is search operations and to define the uniqueness property in sets and tables (uniqueness of keys).<br />
# Classic EiffelBase uses the boolean <e>object_comparison</e> attribute in <e>CONTAINER</e> for this purpose.<br />
# Gobo.structures uses another approach: storing equivalence as an object of a specific class, which can be redefined by the user to implement an arbitrary equalivalence relation.<br />
# A similar approach would be to use agents to store the equalivalence relation (no need to create classes). The downside is that agents do not serialize well.<br />
# Another approach is to make <e>has (x: G)</e> and <e>search (x: G)</e> always use <e>=</e>, but also introduce <e>exists (p: PREDICATE [ANY, TUPLE [G]])</e> and <e>satisfy (p: PREDICATE [ANY, TUPLE [G]])</e>. This is more flexible (better fits cases when the predicate is not an equivalence), but duplicates the number of search features and doesn't solve the problem with sets.<br />
<br />
Additional question (if the comparison criterion is stored in the container) is whether it can be changed during the object lifetime. A well known practice is that in sets it is not allowed to change if the set is not empty. This gives rise to <e>changeable_comparison_criterion</e> query in CONTAINER.<br />
Note that for most set and table implementations (hashed, sorted) the comparison critearion is defined by the corresponding hash function, order, etc. and cannot be modified arbitrary even when the set or table is empty.<br />
<br />
The strategy chosen in EiffelBase2 is to treat differently comparison criteria on which a set or a table is based and ones just used for search. For the first the Gobo approach is taken (2 in the list above), because it is more flexible than in EiffelBase, as we can use whatever equivalence relation we want instead of just <e>is_equal</e> (useful for library classes). Moreover, the equivalence relation is passed as an argument to the creation procedure and cannot be changed afterward. <br />
<br />
For search operations the approach 4 is taken, because it doesn't clutter the container state with properties that don't pertain to the container itself, but to specific search operations.<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13791EiffelBase22010-04-23T13:19:52Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase.<br />
In the design inspired by external iterators we found it natural to separate ''containers'' (with their measurements and modification means) from interfaces to access elements of containers, here called ''observers''.<br />
<br />
On the observer side we distinguish ''maps'' (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either ''used'' by a container (as a supplier) or ''inherited'' by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal acess mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like RANDOM it makes sense to ''inherit'' from an iterator, because they cannot have more than one active iterator.<br />
<br />
On the other side, a ''container'' is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called ''streams'').<br />
<br />
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from CONTAINER. There is one exception: SEQUENCE, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.<br />
<br />
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers. <br />
[[Image:eb2_container.png|800px|thumb|none|Container class hierarchy]]<br />
<br />
The second one is a hierarchy of streams and iterators.<br />
[[Image:eb2_iterator.png|800px|thumb|none|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13790EiffelBase22010-04-23T12:51:43Z<p>Kenga: </p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
[[Image:eb2_container.png|800px|frameless|left|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|800px|frameless|left|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13789EiffelBase22010-04-23T12:49:05Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
[[Image:eb2_container.png|800px|thumb|left|Container class hierarchy]]<br />
<br />
[[Image:eb2_iterator.png|800px|thumb|left|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13788EiffelBase22010-04-23T12:48:34Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
[[Image:eb2_container.png|800px|thumb|left|Container class hierarchy]]<br />
[[Image:eb2_iterator.png|800px|thumb|left|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kengahttps://dev.eiffel.com/index.php?title=File:Eb2_iterator.png&diff=13787File:Eb2 iterator.png2010-04-23T12:47:03Z<p>Kenga: Class diagram of the iterator classes in EiffelBase2 library.</p>
<hr />
<div>Class diagram of the iterator classes in EiffelBase2 library.</div>Kengahttps://dev.eiffel.com/index.php?title=EiffelBase2&diff=13786EiffelBase22010-04-23T12:46:32Z<p>Kenga: /* Design overview */</p>
<hr />
<div>[[Category:Library]]<br />
<br />
==Overview==<br />
<br />
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the [[EiffelBase]] library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development. <br />
<br />
==Design goals==<br />
<br />
The design goals for EiffelBase2 are:<br />
<br />
*Verifiability. The library is designed to allow proofs of correctness.<br />
<br />
*Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.<br />
<br />
*Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).<br />
<br />
*As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.<br />
<br />
*Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).<br />
<br />
*Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.<br />
<br />
==Design overview==<br />
[[Image:eb2_container.png|left|Container class hierarchy]]<br />
[[Image:eb2_iterator.png|left|Iterator class hierarchy]]<br />
<br />
==Model-based contracts==<br />
<br />
==Status and roadmap==<br />
<br />
Development of EiffelBase has started as a project at ETH Zurich; see the [http://eiffelbase2.origo.ethz.ch/ project page]. Documentation and other material will soon be transferred to the present page.</div>Kenga