Bertrand Meyer: Basic Eiffel language mechanisms <p> </head> <p> <!----------- Start of body -----------------------------------> <body> <p> <h1>Basic Eiffel language mechanisms</br> Bertrand Meyer, August 2006</h1> <p> <p> This document is a quick summary of Eiffel language mechanisms. It relies on the ECMA standard but indicates which constructs are not yet supported by current compilers. <p> The aim is not to provide a complete introduction to the language (for that, the best reference is the introduction to the ECMA standard), but to enable programmers familiar with other languages to see quickly what's original (and not) in Eiffel. <h2>Overall structure</h2> An Eiffel "<B>system</B>" (or "program") is a collection of <B>classes</B>. The class is the major unit of decomposition. <p> <p> At the level above classes: there is a notion of "<B>cluster</B>". A cluster is essentially a group of classes, and possibly subclusters since clusters can be nested. But there is no language construct for "cluster"; this is an organizational tool left to the environment. Typically (but again this is not prescribed): <ul> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Each class will be in a separate file (standard convention: x.e for the file name if the class is called X). <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Each cluster will be in a directory (folder) containing such class files; subclusters are in subdirectories. </ul> <p> At the level below classes: a class contains <B>features</B> (roughly corresponding to "members" in e.g. C++), a class invariant, and some other properties such as a "notes" section for documentation. <p> Any system must have a class designated as "root", and one of its creation procedures designated as "root procedure". Executing the system consists of creating an instance of the root class and executing its root procedure. (Of course this generally creates new objects, calls new features etc.) <p> <h2>Features, commands, queries</h2> The primary characteristic of a class is that it contains a set of features. As a class represents a set of run-time objects (its instances), a feature is an operation on these objects. Operations are of two kinds: <ul> <p> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Queries, which give information about an instance. <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Commands, which modify an instance. </ul> <p> This distinction is important to the Eiffel method. In particular: <p> <ul> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Uniform Access Principle: from the outside, whether a query is an attribute (field in each object) or a function (algorithm) should not make any difference. For example a_vehicle.speed could be an attribute, accessed from the object's representation; or it could be computed by a function that divides distance by time. The notation is the same in both cases, so that it's easy to change representation without affecting the rest of the software. <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Command-Query Separation Principle: Queries must not modify the instance. This is not a language rule but a methodological principle. So in good Eiffel style one does not find "get" function that change something and return a result; instead there are commands (procedures) to change objects, and queries to obtain information about the object, resulting from preceding changes. </ul> <p> <h2>Feature names and no-overloading</h2> <p> An important property of Eiffel is that a class is fundamentally a mapping from feature names to features. More plainly said this means that one name, within one class, means one thing. This keeps things simple and in particular is what makes the multiple inheritance mechanism possible (see below). <p> Names can, of course, be reused in different classes, but in a given class if you need another feature you'll have to invent another name. This is really no limitation since the conventional kinds of overloading are, in an object-oriented perspective, applied to different classes. For example if you want to have several versions of <font color="blue">"+"</font>: <p> <pre> <font color="blue"><I>a</I> + <I>b</I></font> for <font color="blue"><I>a</I>, <I>b</I>: <I>INTEGER</I></font> <font color="blue"><I>a</I> + <I>b</I></font> for <font color="blue"><I>a</I>, <I>b</I>: <I>REAL</I></font> <font color="blue"><I>a</I> + <I>b</I></font> for <font color="blue"><I>a</I>, <I>b</I>: <I>VECTOR</I> [<I>INTEGER</I>]</font> </pre> <p> then in Eiffel it simply means that the three classes involved each have a feature <p> <pre> <font color="blue"><I>plus</I> <B>alias</B> "+" (<I>other</I>: <I>XXX</I>): <I>XXX</I></font> </pre> <p> where <font color="blue"><I>XXX</I></font> is the given class (<font color="blue"><I>INTEGER</I></font>, <font color="blue"><I>REAL</I></font>, <font color="blue"><I>VECTOR</I> [<I>G</I>])</font>. (See "Operator and bracket syntax, assigner commands" below.) All the usual forms of operator overloading are thus supported; in fact the mechanism (unlike in most languages) leaves considerable freedom in making up new operators, as may be needed in scientific and engineering applications. What is not possible is the kind of argument overloading where a given class has both a feature <font color="blue"><I>f</I> (<I>x</I>: <I>X</I>)</font> and another <font color="blue"><I>f</I> (<I>y</I>: <I>Y</I>)</font> with the same names. I have discussed [1] how such overloading is useless, damages readability, and complicates the language mechanism needlessly. <h2>Design by Contract in Eiffel</h2> <p> The concepts of Design by Contract are central to Eiffel. The mechanisms are tightly integrated with the language. The basic constructs are: <p> <ul> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Routine precondition <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Routine postcondition <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> Class invariant </ul> <p> In addition, the language supports a "Check instruction" (a kind of "assert") and, in the syntax for loops, clauses for a loop invariant and a loop variant. <p> As defined in the Design by Contract methodology, contracts guide redefinition of features in inheritance. Specifically, in a redefinition: <p> <ul> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> The precondition can only be weakened, to ensure that any call that met the requirements of the original version still meets those of the redefined one. The keyword in that case is no longer <font color="blue"><B>require</B></font> but <font color="blue"><B>require else</B></font>. <p> <p><img src="/~meyer/images/icons/greenball.gif" alt="+"> The postcondition can only be strengthened, to ensure that any result guaranteed by the original version is still provided by the redefined one. The keyword in that case is no longer <font color="blue"><B>ensure</B></font> but <font color="blue"><B>ensure then</B></font>. </ul> <p> <h2>Genericity</h2> Classes can be generic, to express that they are parameterized by types. Generic parameters appear in square brackets: <pre> <font color="blue"><B>class</B> <I>LIST</I> [<I>G</I>] ...</font> </pre> <p> G is known as a "formal generic parameter". (Eiffel reserves "argument" for routines, and uses "parameter" only for generic classes.) With such a declaration G represents within the class an arbitrary type; so a function can return a value of type G, and a routine can take an argument of that type: <p> <pre> <font color="blue"><I>item</I>: <I>G</I> <B>do</B> ... <B>end</B> <I>put</I> (<I>x</I>: <I>G</I>) <B>do</B> ... <B>end</B></font> </pre> <p> The <font color="blue"><I>LIST</I> [<I>INTEGER</I>]</font> and <font color="blue"><I>LIST</I> [<I>WORD</I>]</font> are "generic derivations" of this class. Permitted combinations(with <font color="blue"><I>n</I>: <I>INTEGER</I></font>, <font color="blue"><I>w</I>: <I>WORD</I></font>, <font color="blue"><I>il</I>: <I>LIST</I> [<I>INTEGER</I>]</font>, <font color="blue"><I>wl</I>: <I>LIST</I> [<I>WORD</I>]</font>) are <p> <pre> <font color="blue"><I>n</I> := <I>il</I>.<I>item</I> <I>wl</I>.<I>put</I> (<I>w</I>)</font> </pre> <p> <font color="blue"><I>INTEGER</I></font> resp. <font color="blue"><I>WORD</I></font> are the "actual generic parameters" in these generic derivations. <p> It is also possible to have <B>constrained</B> formal parameters, for which the actual parameter must inherit from a given class, the "constraint". For example in <p> <pre> <font color="blue"><B>class</B> <I>HASH_TABLE</I> [<I>G</I>, <I>KEY</I> -> <I>HASHABLE</I>]</font> </pre> <p> a derivation <font color="blue"><I>HASH_TABLE</I> [<I>INTEGER</I>, <I>STRING</I>]</font> is valid only if <font color="blue">STRING</font> inherits from <font color="blue"><I>HASHABLE</I></font> (as it it indeed does in typical Eiffel libraries). Within the class, having <font color="blue">KEY</font> constrained by <font color="blue"><I>HASHABLE</I></font> means that for <font color="blue"><I>x</I>: <I>KEY</I></font> it is possible to apply to <font color="blue">x</font> all the features of <font color="blue"><I>HASHABLE</I></font>, as in <font color="blue"><I>x</I>.<I>hash_code</I></font>. <p> <h2>Inheritance basics</h2> <p> To inherit from one or more others, a class will include a <font color="blue"><B>inherit</B></font> clause at the beginning: <p> <pre> <font color="blue"><B>class</B> <I>C</I> <B>inherit</B> <I>A</I> <I>B</I> ... Rest of class declaration ...</font> </pre> <p> The class may redefine (override) some or all of the inherited features. This must be explicitly announced at the beginning of the class through a <font color="blue"><B>redefine</B></font> subclause of the inheritance clause, as in <p> <pre> <font color="blue"><B>class</B> <I>C</I> <B>inherit</B> <I>A</I> <B>redefine</B> <I>f</I>, <I>g</I>, <I>h</I> <B>end</B> <I>B</I> <B>redefine</B> <I>u</I>, <I>v</I> <B>end</B></font> </pre> <p> Then the class will contain new declarations of the features listed, which locally override the inherited ones. <p> Such declarations would be invalid in the absence of a <font color="blue"><B>redefine</B></font> subclause since the class would then violate the no-overloading principle. The subclause, of course, also helps for readability, by announcing at the top of a class what functionality it adapts from the given parent. <p> Eiffel fully applies dynamic binding: in a feature call <font color="blue"><I>x</I>.<I>f</I></font> the version to be called is always the one applicable to the class of the object denoted by <font color="blue"><I>x</I></font> at the time of execution. Eiffel has no "static binding", except as a compiler optimization. (In C++ terms: all functions þave the same semantics as if they had been declared "virtual"; finding out that a particular function doesn't need dynamic binding is the responsibility of the compiler, not the programmer.) <h2>Non-conforming inheritance</h2> <p> Inheritance normally allows polymorphism (and hence subtyping): if <font color="blue"><I>B</I></font> inherits from if <font color="blue"><I>A</I></font>, then <font color="blue"><I>x</I> := <I>y</I></font> is legal for <font color="blue"><I>x</I></font> of type <font color="blue"><I>x</I></font> <font color="blue"><I>A</I></font> and <font color="blue"><I>y</I></font> of type <font color="blue"><I>B</I></font>. <p> Sometimes inheritance is for reuse only and is not intended for polymorphism. In such cases the <font color="blue"><B>inherit</B></font> clause should start with <pre> <font color="blue"><B>inherit</B> {<I>NONE</I>}</font> </pre> <p> This facility is, however, not yet supported by current compilers. <h2>Deferred classes</h2> <p> If instead of ```class''', a class starts with ```deferred class''', it is not meant to have direct instances: an instruction ```create''' ``x...'', with ``x'' of the corresponding type, is invalid. Only "effective" (non-deferred) descendants of the class can be instantiated. <p> A feature can itself be declared ```deferred''; the ```deferred''' keyword replaces the ```do''' clause, so the feature has no implementation. As soon as a class has at least one deferred feature, it must itself be marked as deferred. The reverse is not true: one can mark a class deferred to prevent instantiation even if all its features are effective. <p> Deferred classes (also called abstract classes) are similar to the "interfaces" of languages like Java and C#, but with an important difference: there is no need for a deferred class to be all deferred. Partially deferred classes play an important role in the Eiffel method's "seamless development", which suggests a continuous development process. The first version of a class, at the analysis or design stage, can be fully deferred, and then follow a succession of continuous refinements through inheritance until it gets to a fully effective stage. <h2>Multiple and repeated inheritance</h2> <p> [To be completed.] <p> <h2>Renaming</h2> A class that inherits from one or more others gets all its features, by default under their original names. It may, however, change their names through a <font color="blue"><B>rename</B></font> clauses. This is required in the case of multiple inheritance if there are name clashes between inherited features; without renaming, the resulting class would violate the no-overloading principle noted above and hence would be invalid. <p> <h2>Tuples</h2> Tuples types may be viewed as a simple form of class, providing only attributes and the corresponding "setter" procedure. A typical tuple type reads <p> <pre> <font color="blue"><I>TUPLE</I> [<I>name</I>: <I>STRING</I>; <I>weight</I>: <I>REAL</I>; <I>date</I>: <I>DATE</I>]</font> </pre> <p> and could be use to describe a simple notion of birth record if a class is not needed. An instance of such a tuple is simply a sequence of values with the given types, given in brackets, such as <p> <pre> <font color="blue">["Brigitte", 3.5, <I>Last_night</I>]</font> </pre> <p> Components of such a tuple can be accessed as if the tuple tags were attributes of a class, for example if <font color="blue"><I>t</I>]</font> has been assigned the above tuple then <font color="blue"><I>t</I>.<I>weight</I>]</font> has value 3.5. <p> Thanks to the notion of assigner command (see below), dot notation can also be used to assign components of such a tuple, as in <p> <pre> <font color="blue"><I>t</I>.<I>weight</I> := <I>t</I>.<I>weight</I> + 0.5</font> </pre> <p> The tuple tags are optional, so that it is also possible to write a tuple type as <font color="blue"><I>TUPLE</I> [<I>STRING</I>, <I>REAL</I>, <I>DATE</I>]</font>. (In some compilers this is the only form of tuple, as tags were introduced with the ECMA standard.) <p> The precise specification of e.g. <font color="blue"><I>TUPLE</I> [<I>A</I>, <I>B</I>, <I>C</I>]</font> is that it describes sequences of <I>at least</I> three elements, the first three being of types <font color="blue"><I>A</I></font>, <font color="blue"><I>B</I></font>, <font color="blue"><I>C</I></font> respectively. As a result <font color="blue"><I>TUPLE</I> [<I>A</I>, <I>B</I>, <I>C</I>]</font> conforms to (may be assigned to) <font color="blue"><I>TUPLE</I> [<I>A</I>, <I>B</I>]</font>, to <font color="blue"><I>TUPLE</I> [<I>A</I>]</font> and to <font color="blue"><I>TUPLE</I></font> (without parameters), the topmost tuple type to which all tuple types conform. <p> <h2>Agents</h2> Eiffel provides an "agent" mechanism to wrap operations into objects. This is useful for iteration, event-driven programming, and other applications for which it is useful to pass operations around the program structure. Agents correspond to lambda calculus and to "closures"; they make it possible to combine the object-oriented paradigm with a significant set of mechanisms available in functional programming languages. <p> For example, to iterate a certain action over a list, it suffices to write <p> <pre> <font color="blue"><I>my_list</I>.<I>do_all</I> (<B>agent</B> <I>my_action</I>)</font> </pre> <p> or, if the action is to be executed only on elements satisfying a certain condition: <p> <pre> <font color="blue"><I>my_list</I>.<I>do_all</I> (<B>agent</B> <I>my_action</I>, <B>agent</B> <I>my_test</I>)</font> </pre> <p> In these examples, <font color="blue"><I>my_action</I></font> and <font color="blue"><I>my_test</I></font> are routines. Prefixing them with <font color="blue"><B>agent</B></font> yields an object that represents the corresponding routine with all its properties, in particular the ability to be called with the appropriate arguments. So if <font color="blue"><I>a</I></font> represents that object (for example because <font color="blue"><I>a</I></font> is the argument to <font color="blue"><I>do_all</I></font>), the instruction <p> <pre> <font color="blue"><I>a</I>.<I>call</I> ([<I>x</I>])</font> </pre> <p> will call the original routine with the argument <font color="blue"><I>x</I></font>, as if we had directly called the original routine: <font color="blue"><I>my_action</I> (<I>x</I>)</font>. Arguments to <font color="blue"><I>call</I></font> are passed as a tuple, here <font color="blue">[<I>x</I>]</font>. <p> It is possible to keep some arguments to an agent <B>open</B> and make others <B>closed</B>. The open arguments are passed as arguments to <font color="blue"><I>call</I></font>: they are provided at the time of agent <I>use</I>. The closed arguments are provided at the time of agent <I>definition</I>. For example, if <font color="blue"><I>action2</I></font> has two arguments, the iteration <p> <pre> <font color="blue"><I>my_list</I>.<I>do_all</I> (<B>agent</B> <I>action2</I> (<B>?</B>, <I>y</I>)</font> </pre> <p> iterates <font color="blue"><I>action2</I> (<I>x</I>, <I>y</I>)</font> for successive values of <font color="blue"><I>x</I></font>, where the second arguments remained set to <font color="blue"><I>y</I></font>. The question mark <font color="blue"><B>?</B></font> indicates an open argument; <font color="blue"><I>y</I></font> is a closed argument of the agent. Note that the basic syntax <font color="blue"><B>agent</B> <I>f</I></font> is a shorthand for <font color="blue"><B>agent</B> <I>f</I> (<B>?</B>, <B>?</B>, ...)</font> with all arguments open. It is also possible to make the <I>target</I> of an agent open through the notation <font color="blue">{<I>T</I>}<B>?</B></font> where <font color="blue"><I>T</I></font> is the type of the target. <p> The distinction between open and closed operands (operands = arguments + target) corresponds to the distinction between bound and free variables in lambda calculus. An agent expression such as <font color="blue"><I>action2</I> (<B>?</B>, <I>y</I>)</font> with some operands closed and some open corresponds to a version of the original operation <I>curried</I> on the closed operands. <p> The agent mechanism has been recently generalized to allow defining an agent without reference to an existing routine (such as <font color="blue"><I>my_action</I></font>, <font color="blue"><I>my_test</I></font>, <font color="blue"><I>action2</I></font>), through inline agents as in <p> <pre> <font color="blue"><I>my_list</I>.<I>do_all</I> (<B>agent</B> (<I>x</I>: <I>INTEGER</I>) <B>require</B> positive: <I>x</I> > 0 <B>do</B> <I>x</I> := <I>x</I> – 1 <B>ensure</B> <I>x</I> = <B>old</B> <I>x</I> – 1 <B>end</B> )</font> </pre> <p> The inline agent passed here can have all the trappings of a normal routine, including precondition, postcondition, rescue clause (not used here), and a full signature. This avoids defining routines when all that's needed is a computation to be wrapped in an agent. This is useful in particular for contracts, as in an invariant clause that expresses that all elements of a list are positive: <p> <pre> <font color="blue"><I>my_list</I>.<I>for_all</I> (<B>agent</B> (<I>x</I>: <I>INTEGER</I>): <I>BOOLEAN</I> <B>do</B> <I>Result</I> := (<I>x</I> > 0) <B>end</B>)</font> </pre> <p> The current agent mechanism leaves a possibility of run-time type error (if a routine with <I>n</I> arguments is passed to an agent expecting <I>m</I> arguments with <I>m</I> < <I>n</I>). This can be avoided by a run-time check through the precondition <font color="blue"><I>valid_arguments</I></font> of <font color="blue"><I>call</I></font>. Several proposals for a purely static correction of this problem are available, including a language change proposal by Ribet et al. [2]. <p> <h2>Once routines</h2> A routine can be declared "once" (with the keyword <font color="blue"><B>once</B></font> replacing the more common <font color="blue"><B>do</B></font>) to indicate that it will only be executed on the first call. Subsequent calls have no further effect; in the case of a function, they return the same value as the first, for example a reference to the same object. <p> "Once" functions serve in particular to provide shared objects; the first call will create the object, subsequent ones will return the reference to that object. The typical scheme is <p> <pre> <font color="blue"><I>shared_object</I>: <I>SOME_TYPE</I> <B>do</B> <B>create</B> <B>Result</B>.<I>make</I> (<I>args</I>) -- This creates the object and returns a reference to it through <B>Result</B> <B>end</B></font> </pre> <p> While the reference remains the same, later calls of the form <font color="blue"><I>shared_object</I>.<I>do_something</I></font> can change the <I>content</I> of the object. <p> "Once" procedures can take care of initialization: several clients of a certain libraries can include a call to the initialization procedure, but only the first such call to happen will actually have an effect. The goal is to achieve decentralized initialization, avoiding the need for an initialization module (which could damage the modular structure of the program). <p> The ECMA specification allows variants of "once" (qualified by a keyword in parentheses, e.g. <font color="blue"><B>once</B> (THREAD)</font>: once per process, once per thread, once per object. This is not, however, fully implemented yet by current compilers (typically, only PROCESS and THREAD). <p> <h2>Conversions</h2> Eiffel provides a mechanism to allow conversions between various types. The mechanisms coexists with inheritance and complements it. To avoid any confusion between the two mechanisms, the design enforces the following principle: <p> (Conversion principle) A type may not both conform and convert to another <p> For example <font color="blue"><I>NEWSPAPER</I></font>may conform to to <font color="blue"><I>PUBLICATION</I></font>, but <font color="blue"><I>INTEGER</I></font> converts to <font color="blue"><I>REAL</I></font> (and does not inherit from it). <p> The conversion mechanism simply generalizes the ad hoc conversion rules (such as indeed between <font color="blue"><I>INTEGER</I></font>and <font color="blue"><I>REAL</I></font>) that exist in most programming languages, making them applicable to any type as long as the above principle is observed. For example a <font color="blue"><I>REAL</I></font> class may be declared to convert to <font color="blue"><I>REAL</I></font>; this makes it possible to create a string from a date simply through <p> <pre> <font color="blue"><I>my_string</I> := <I>my_date</I></font> </pre> <p> as a shortcut for using an explicit object creation with a conversion procedure: <p> <pre> <font color="blue"><B>create</B> <I>my_string</I>.<I>make_from_date</I> (<I>my_date</I>)</font> </pre> <p> To make the first form possible as a synonym for the first, it suffices to list the creation procedure (constructor) <font color="blue"><I>make_from_date</I></font> in a <font color="blue"><B>convert</B></font> clause at the beginning of the class. <p> As another example, if there is such a conversion procedure listed from <font color="blue"><I>TUPLE</I> [<I>day</I>: <I>INTEGER</I>; <I>month</I>: <I>STRING</I>; <I>year</I>: <I>INTEGER</I>]]</font>, then one can directly assign a tuple to a date, causing the appropriate conversion, as in <p> <pre> <font color="blue"><I>Bastille_day</I> := [14, "July", 1789]</font> </pre> <p> <p> <h2>Exception handling</h2> [To be completed.] <p> <h2>Operator and bracket syntax, assigner commands</h2> <p> Eiffel's view of computation is completely object-oriented in the sense that every operation is relative to an object, the "target". So for example an addition <p> <pre> [1] <font color="blue"><I>a</I> + <I>b</I></font> </pre> <p> is conceptually understood as if it were a function call <p> <pre> [2] <font color="blue"><I>a</I>.<I>plus</I> (<I>b</I>)</font> </pre> <h2>References</h2> [Incomplete, others will be added.] <p> [1] <I>Overloading vs Object Technology</I>, in <I>Journal of Object-Oriented Programming</I> (JOOP), vol. 14, no. 4, October-November 2001, available <a href="http://se.ethz.ch/~meyer/publications/joop/overloading.pdf ">online</a>. <p> [2] Ribet, Cyril Adrian, Olivier Zendra, Dominique Colnet: <I>Conformance of agents in the Eiffel language</I>, in JOT: <I<Journal of Object Technology</I>, vol. 3, no. 4, April 2004, Special issue: TOOLS USA 2003, pp. 125-143. Available on line from the <a href="http://www.jot.fm/issues/issue_2004_04/article7">JOT article page</a>. <p> ©2006, Bertrand Meyer (based on material from "Eiffel: The language"), © Bertrand Meyer, 1990. <!--------------- Start bottom links ---------------------------------------> <center> <table border="0" cellspacing="0" cellpadding="0"><tr><td> <p> <hr> <nobr> <a href="http://www.inf.ethz.ch/~meyer">Meyer home</a>  -   <a href="http://www.inf.ethz.ch/~meyer/publications/">Publications</a>  -  <a href="http://www.inf.ethz.ch/~meyer/events/">Events</a>  -  <a href="http://se.inf.ethz.ch/">Chair of Software Engineering</a>  -  <a href="http://www.inf.ethz.ch/">CS Department</a> </nobr> <hr> </td><td width="30%"> </td></tr></table> </center> <!--------------- End bottom links -----------------------------------------> <p> <p> </td></tr></table> </body></html> <p>