Content deleted Content added
Link suggestions feature: 3 links added. |
|||
(482 intermediate revisions by more than 100 users not shown) | |||
Line 1:
{{Short description|Object-oriented programming language}}
{{Infobox programming language
| name = Eiffel
| logo = Eiffel logo.svg
| logo caption = Logo
| paradigm = [[Programming paradigm|Multi-paradigm]]: [[Object-oriented programming|object-oriented]], [[Class-based programming|class-based]], [[Generic programming|generic]], [[Concurrent object-oriented programming|concurrent]]
| designer = [[Bertrand Meyer]]
| developer =
| released = {{Start date and age|1986}}<ref>{{cite web |title=Eiffel in a Nutshell |url=https://archive.eiffel.com/eiffel/nutshell.html |date=1985–2012 |website=Eiffel Software |language=en |access-date=29 November 2024}}</ref>
| latest release version = [[EiffelStudio]] 24.05<ref>{{cite web |title=EiffelStudio 24.05 is available! |url=https://www.eiffel.org/blog/eiffelstudio_24_05 |date=14 June 2024 |website=Eiffel.org |access-date=29 November 2024}}</ref>
| latest release date = {{Start date and age|2024|06|14|df=y}}
| typing = [[Static typing|static]]
| implementations = [[EiffelStudio]], [[LibertyEiffel]], [[SmartEiffel]], [[Visual Eiffel]], Gobo Eiffel, "The Eiffel Compiler" tecomp
|
| platform = [[Cross-platform software|Cross-platform]]
| operating system = [[FreeBSD]], [[Linux]], [[macOS]], [[OpenBSD]], [[Oracle Solaris|Solaris]], [[Windows]]
| license = dual and enterprise
| file ext = <code>.e</code>
| website = {{URL|eiffel.org}}
| dialects =
| influenced by = [[Ada (programming language)|Ada]], [[Simula]], [[Z notation|Z]]
| influenced = [[Ada (programming language)|Ada 2012]], [[C Sharp (programming language)|C#]], [[D (programming language)|D]], [[Java (programming language)|Java]], [[Racket (programming language)|Racket]], [[Ruby (programming language)|Ruby]],<ref name="nov2pro">{{cite book |last1=Cooper |first1=Peter |year=2009 |title=Beginning Ruby: From Novice to Professional |edition=2nd |series=Beginning from Novice to Professional |publisher=APress |___location=Berkeley |isbn=978-1-4302-2363-4 |page=101 |quote=To a lesser extent, Python, LISP, Eiffel, Ada, and C++ have also influenced Ruby.}}</ref> [[Sather]], [[Scala (programming language)|Scala]]
}}
'''Eiffel''' is an [[Object-oriented programming|object-oriented]] [[programming language]] designed by [[Bertrand Meyer]] (an object-orientation proponent and author of ''[[Object-Oriented Software Construction]]'') and Eiffel Software. Meyer conceived the language in 1985 with the goal of increasing the reliability of commercial software development.<ref>{{cite web |title=Eiffel – the Language |url=http://www.berenddeboer.net/eiffel/archive/halstenbach_eiffel_history.html |access-date=6 July 2016 |website=berenddeboer.net}}</ref> The first version was released in 1986. In 2005, the [[International Organization for Standardization]] (ISO) released a [[technical standard]] for Eiffel.
The design of the
Many concepts initially introduced by Eiffel
==Characteristics==
The key characteristics of the Eiffel language include:
* An object-oriented program structure in which a class serves as the basic unit of decomposition.<ref>{{cite web | title=Programming Languages - Eiffel | website=Department of Computer Science, Virginia Tech | url=https://courses.cs.vt.edu/~cs3304/Spring02/lectures/lect12.pdf | access-date=25 March 2023}}</ref>
* [[Design by contract]] tightly integrated with other language constructs.
* Automatic memory management, typically implemented by [[Garbage collection (computer science)|garbage collection]].<ref>{{cite web | author=Carl Friess|title=Eiffel Syntax Guide | website=Eiffel Syntax Guide | url=https://eiffel-guide.com/ | access-date=25 March 2023}}</ref>
* [[Inheritance (object-oriented programming)|Inheritance]], including [[multiple inheritance]], [[wikt:renaming|renaming]], [[Method overriding|redefinition]], "select", [http://docs.eiffel.com/book/method/et-inheritance#Non-conforming_inheritance non-conforming inheritance], and other mechanisms intended to make inheritance safe.
* Constrained and unconstrained [[generic programming]]<ref name="Claus">{{cite web | author=Claus Brabrand |title=The E I F F E L Programming Language | website=IT University of Copenhagen | url=http://www.itu.dk/people/brabrand/GSD-2013/Eiffel.pdf | access-date=25 March 2023}}</ref>
* A uniform [[type system]] handling both value and reference semantics
* [[Static typing]]
* [[Void safety]], or static protection against calls on null references, through the attached-types mechanism.
* Agents, or objects that wrap computations, closely connected with [[Closure (computer science)|closure]]s and [[lambda calculus]].
* ''Once'' routines, or routines evaluated only once, for object sharing and decentralized initialization.
* Keyword-based syntax in the [[ALGOL]]/[[Pascal (programming language)|Pascal]] tradition but separator-free, insofar as semicolons are optional, with operator syntax available for routines.
* Case insensitivity
* Simple Concurrent Object-Oriented Programming ([[SCOOP (software)|SCOOP]]) facilitates creation of multiple, concurrently active execution vehicles at a level of abstraction above the specific details of these vehicles (e.g. multiple threads without specific mutex management).
==
Eiffel emphasizes [[Declarative programming|declarative]] statements over [[Procedural programming|procedural]] code and attempts to eliminate the need for bookkeeping instructions.
Eiffel shuns coding tricks or
==
Eiffel was originally developed by
The design goal
Eiffel's design is based on object-oriented programming theory, with only minor influence of other
===
[[EiffelStudio]] is an [[integrated development environment]] available under either an [[Open-source license|open source]] or a commercial license. It offers an object-oriented environment for [[software engineering]]. EiffelEnvision is a plug-in for [[Microsoft Visual Studio]] that allows users to edit, compile, and debug Eiffel projects from within the Microsoft Visual Studio IDE. Five other [[Open-source software|open source]] implementations are available: "The Eiffel Compiler" tecomp; Gobo Eiffel; [[SmartEiffel]], the GNU implementation, based on an older version of the language; [[LibertyEiffel]], based on the SmartEiffel compiler; and [[Visual Eiffel]].
Several other programming languages incorporate elements first introduced in Eiffel. [[Sather]], for example, was originally based on Eiffel but has since diverged, and now includes several [[functional programming]] features. The interactive-teaching language Blue, forerunner of [[BlueJ]], is also Eiffel-based. The [[Apple Media Tool]] includes an Eiffel-based Apple Media Language.
===Specifications and standards===
The Eiffel language definition is an international standard of the [[International Organization for Standardization|ISO]]. The standard was developed by [[European Computer Manufacturers Association|ECMA International]], which first approved the standard on 21 June 2005 as Standard ECMA-367, Eiffel: Analysis, Design and Programming Language. In June 2006, ECMA and ISO adopted the second version. In November 2006, ISO first published that version. The standard can be found and used free of charge on the ECMA site.<ref>ECMA International: Standard ECMA-367{{snd}} Eiffel: Analysis, Design and Programming Language 2nd edition (June 2006); available online at [https://ecma-international.org/publications-and-standards/standards/ecma-367/ https://ecma-international.org/publications-and-standards/standards/ecma-367/]</ref> The ISO version<ref>International Organization for Standardization: Standard ISO/IEC DIS 25436, available online at [http://www.iso.org/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=42924&ICS1=35&ICS2=60&ICS3=]</ref> is identical in all respects except formatting.
Eiffel Software, "The Eiffel Compiler" tecomp and Eiffel-library-developer Gobo have committed to implementing the standard; Eiffel Software's EiffelStudio 6.1 and "The Eiffel Compiler" tecomp implement some of the major new mechanisms—in particular, inline agents, assigner commands, bracket notation, non-conforming inheritance, and attached types. The [[SmartEiffel]] team has turned away from this standard to create its own version of the language, which they believe to be closer to the original style of Eiffel. Object Tools has not disclosed whether future versions of its Eiffel compiler will comply with the standard. [[LibertyEiffel]] implements a dialect somewhere in between the [[SmartEiffel]] language and the standard.
The standard cites the following, predecessor Eiffel-language specifications:
* Bertrand Meyer: ''Eiffel: The Language'', Prentice Hall, second printing, 1992 (first printing: 1991)
* Bertrand Meyer: ''Standard Eiffel'' (revision of preceding entry), ongoing, 1997–present, at Bertrand Meyer's ETL3 page, and
* Bertrand Meyer: ''Object-Oriented Software Construction'', Prentice Hall: first edition, 1988; second edition, 1997.
* Bertrand Meyer: ''Touch of Class: Learning to Program Well with Objects and Contracts'', [[Springer Science+Business Media|Springer-Verlag]], 2009 {{ISBN|978-3-540-92144-8}} lxiv + 876 pages Full-color printing, numerous color photographs
The current version of the standard from June 2006 contains some inconsistencies (e.g. covariant redefinitions){{Citation needed|date=October 2010}}. The ECMA committee has not yet announced any timeline and direction on how to resolve the inconsistencies.
==
===Overall structure===
An Eiffel "system" or "program" is a collection of ''classes''. Above the level of classes, Eiffel defines ''cluster'', which is essentially a group of classes, and possibly of ''subclusters'' (nested clusters). Clusters are not a syntactic [[language construct]], but rather a standard organizational convention. Typically an Eiffel program will be organized with each class in a separate file, and each cluster in a directory containing class files. In this organization, subclusters are subdirectories. For example, under standard organizational and casing conventions, <code>x.e</code> might be the name of a file that defines a class called X.
A class contains ''features'', which are similar to "routines", "members", "attributes" or "methods" in other object-oriented programming languages. A class also defines its invariants, and contains other properties, such as a "notes" section for documentation and metadata. Eiffel's standard data types, such as <code>INTEGER</code>, <code>STRING</code> and <code>ARRAY</code>, are all themselves classes.
Every system must have a class designated as "root", with one of its creation procedures designated as "root procedure". Executing a system consists of creating an instance of the root class and executing its root procedure. Generally, doing so creates new objects, calls new features, and so on.
Eiffel has five basic executable instructions: assignment, object creation, routine call, condition, and iteration. Eiffel's control structures are strict in enforcing [[structured programming]]: every block has exactly one entry and exactly one exit.
====Scoping====
Unlike many object-oriented languages, but like [[Smalltalk]], Eiffel does not permit any assignment into attributes of objects, except within the features of an object, which is the practical application of the principle of [[information hiding]] or data abstraction, requiring formal interfaces for data mutation. To put it in the language of other object-oriented programming languages, all Eiffel attributes are "protected", and "setters" are needed for client objects to modify values. An upshot of this is that "setters" can and normally do, implement the invariants for which Eiffel provides syntax.
While Eiffel does not allow direct access to the features of a class by a client of the class, it does allow for the definition of an "assigner command", such as:
<syntaxhighlight lang="eiffel">
some_attribute: SOME_TYPE assign set_some_attribute
set_some_attribute (v: VALUE_TYPE)
-- Set value of some_attribute to `v'.
</syntaxhighlight>
While a slight bow to the overall developer community to allow something looking like direct access (e.g. thereby breaking the Information Hiding Principle), the practice is dangerous as it hides or obfuscates the reality of a "setter" being used. In practice, it is better to redirect the call to a setter rather than implying a direct access to a feature like <code>some_attribute</code> as in the example code above.{{Citation needed|reason=Working fine in Delphi (Object Pascal) for 25 years. In Eiffel, if a setter is the only way to set an attribute, this must obviously be what is going on. How is that 'obfuscated'?|date=March 2021}}
Unlike other languages, having notions of "public", "protected", "private" and so on, Eiffel uses an exporting technology to more precisely control the scoping between client and supplier classes. Feature visibility is checked statically at compile-time. For example, (below), the "{NONE}" is similar to "protected" in other languages. Scope applied this way to a "feature set" (e.g. everything below the 'feature' keyword to either the next feature set keyword or the end of the class) can be changed in descendant classes using the "export" keyword.
<syntaxhighlight lang="eiffel">
feature {NONE} -- Initialization
default_create
-- Initialize a new `zero' decimal instance.
do
make_zero
end
</syntaxhighlight>
Alternatively, the lack of a {x} export declaration implies {ANY} and is similar to the "public" scoping of other languages.
<syntaxhighlight lang="eiffel">
feature -- Constants
</syntaxhighlight>
Finally, scoping can be selectively and precisely controlled to any class in the Eiffel project universe, such as:
<syntaxhighlight lang="eiffel">
feature {DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER} -- Access
</syntaxhighlight>
Here, the compiler will allow only the classes listed between the curly braces to access the features within the feature group (e.g. {{mono|DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER}}).
===="Hello, world!"====
A programming language's look and feel is often conveyed using a [[Hello world program|"Hello, world!"]] program. Such a program written in Eiffel might be:
<syntaxhighlight lang="eiffel">
class
HELLO_WORLD
create
make
feature
make
do
print ("Hello, world!%N")
end
end
</syntaxhighlight>
This program contains the class <code>HELLO_WORLD</code>. The constructor (create routine) for the class, named <code>make</code>, invokes the <code>print</code> system library routine to write a <code>"Hello,</code> <code>world!"</code> message to the output.
===Design by contract===
{{Further|Design by contract}}
The concept of Design by Contract is central to Eiffel. The contracts assert what must be true before a routine is executed (precondition) and what must hold to be true after the routine finishes (post-condition). Class Invariant contracts define what assertions must hold true both before and after any feature of a class is accessed (both routines and attributes). Moreover, contracts codify into executable code developer and designers assumptions about the operating environment of the features of a class or the class as a whole by means of the invariant.
The Eiffel compiler is designed to include the feature and class contracts in various levels. EiffelStudio, for example, executes all feature and class contracts during execution in the "Workbench mode." When an executable is created, the compiler is instructed by way of the project settings file (e.g. ECF file) to either include or exclude any set of contracts. Thus, an executable file can be compiled to either include or exclude any level of contract, thereby bringing along continuous levels of unit and [[integration testing]]. Moreover, contracts can be continually and methodically exercised by way of the Auto-Test feature found in EiffelStudio.
The Design by Contract mechanisms are tightly integrated with the language and guide redefinition of features in inheritance:
* Routine precondition: The precondition may only be weakened by inheritance; any call that meets the requirements of the ancestor meets those of the descendant.
* Routine postcondition: The postcondition can only be strengthened by inheritance; any result guaranteed by the ancestor is still provided by the descendant.
* Class invariant: Conditions that must hold true after the object's creation and after any call to an exported class routine. Because the invariant is checked so often, it makes it simultaneously the most expensive and most powerful form of condition or contract.
In addition, the language supports a "check instruction" (a kind of "assert"), loop invariants, and loop variants (which guarantee loop termination).
===Void-safe capability===
{{Further|Void safety}}
Void-safe ability, like static typing, is another facility for improving software quality. Void-safe software is protected from [[Execution (computing)#Runtime|runtime]] errors caused by calls to [[null reference|void references]], and therefore will be more reliable than software in which calls to void targets can occur. The analogy to static typing is a useful one. Void-safe ability can be seen as an extension to the type system, or a step beyond static typing, because the mechanism for ensuring void safety is integrated into the type system.
The guard against void target calls can be seen by way of the notion of attachment and (by extension) detachment (e.g. detachable keyword). The void-safe facility can be seen in a short re-work of the example code used above:
<syntaxhighlight lang="eiffel">
some_attribute: detachable SOME_TYPE
use_some_attribute
-- Set value of some_attribute to `v'.
do
if attached some_attribute as l_attribute then
do_something (l_attribute)
end
end
do_something (a_value: SOME_TYPE)
-- Do something with `a_value'.
do
... doing something with `a_value' ...
end
</syntaxhighlight>
The code example above shows how the compiler can statically address the reliability of whether <code>some_attribute</code> will be attached or detached at the point it is used. Notably, the <code>attached</code> keyword allows for an "attachment local" (e.g. <code>l_attribute</code>), which is scoped to only the block of code enclosed by the if-statement construct. Thus, within this small block of code, the [[local variable]] (e.g. <code>l_attribute</code>) can be statically guaranteed to be non-void (i.e. void safe).
===Features: commands and queries===
The primary characteristic of a class is that it defines a set of features: as a class represents a set of run-time objects, or "instances", a feature is an operation on these objects. There are two kinds of features: queries and commands. A query provides information about an instance. A command modifies an instance.
The command-query distinction is important to the Eiffel method. In particular:
* [[Uniform-Access Principle]]: from the point of view of a software client making a call to a class feature, whether a query is an attribute (field value) or a function (computed value) should not make any difference. For example, <code>a_vehicle.speed</code> could be an attribute accessed on the object <code>a_vehicle</code>, or it could be computed by a function that divides distance by time. The notation is the same in both cases, so that it is easy to change the class's implementation without affecting client software.
* [[Command-Query Separation|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" functions 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.
===
Eiffel does not allow argument [[Method overloading|overloading]]. Each feature name within a class always maps to a specific feature within the class. One name, within one class, means one thing. This design choice helps the readability of classes, by avoiding a cause of ambiguity about which routine will be invoked by a call. It also simplifies the language mechanism; in particular, this is what makes Eiffel's multiple inheritance mechanism possible.<ref>Bertrand Meyer: Overloading vs Object Technology, in Journal of Object-Oriented Programming (JOOP), vol. 14, no. 4, October–November 2001, available [http://se.ethz.ch/~meyer/publications/joop/overloading.pdf online]</ref>
Names can, of course, be reused in different classes. For example, the feature {{mono|plus}} (along with its infix [[#Operator and bracket syntax, assigner commands|alias]] {{mono|"+"}}) is defined in several classes: {{mono|INTEGER}}, {{mono|REAL}}, {{mono|STRING}}, etc.
===Genericity===
{{See also|Generic programming#Genericity in Eiffel}}
A generic class is a class that varies by type (e.g. LIST [PHONE], a list of phone numbers; ACCOUNT [G->ACCOUNT_TYPE], allowing for ACCOUNT [SAVINGS] and ACCOUNT [CHECKING], etc.). Classes can be generic, to express that they are parameterized by types. Generic parameters appear in square brackets:
<syntaxhighlight lang="eiffel">
class LIST [G] ...
</syntaxhighlight>
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:
<syntaxhighlight lang="eiffel">
put (x: G) do ... end
</syntaxhighlight>
The <code>LIST [INTEGER]</code> and <code>LIST [WORD]</code> are "generic derivations" of this class. Permitted combinations (with <code>n: INTEGER</code>, <code>w: WORD</code>, <code>il: LIST [INTEGER]</code>, <code>wl: LIST [WORD]</code>) are:
<syntaxhighlight lang="eiffel">
n := il.item
wl.put (w)
</syntaxhighlight>
<code>INTEGER</code>
It is also possible to have 'constrained' formal parameters, for which the actual parameter must inherit from a given class, the "constraint". For example, in
<syntaxhighlight lang="eiffel">
class HASH_TABLE [G, KEY -> HASHABLE]
</syntaxhighlight>
a derivation <code>HASH_TABLE [INTEGER, STRING]</code> is valid only if <code>STRING</code> inherits from <code>HASHABLE</code> (as it indeed does in typical Eiffel libraries). Within the class, having <code>KEY</code> constrained by <code>HASHABLE</code> means that for <code>x: KEY</code> it is possible to apply to <code>x</code> all the features of <code>HASHABLE</code>, as in <code>x.hash_code</code>.
===Inheritance basics===
To inherit from one or more others, a class will include
<syntaxhighlight lang="eiffel">
class C inherit
B
-- ... Rest of class declaration ...
</syntaxhighlight>
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 <code>redefine</code> subclause of the inheritance clause, as in
<syntaxhighlight lang="eiffel">
class C inherit
A
B
redefine u, v end
</syntaxhighlight>
See<ref>{{cite web|url=http://archive.eiffel.com/doc/online/eiffel50/intro/language/tutorial-10.html |title=9 INHERITANCE |publisher=Archive.eiffel.com |date=1997-03-23 |access-date=2013-07-08}}</ref> for a complete discussion of Eiffel inheritance.
===Deferred classes and features===
Classes may be defined with <code>deferred class</code> rather than with <code>class</code> to indicate that the class may not be directly instantiated. Non-instantiatable classes are called [[abstract class]]es in some other object-oriented programming languages. In Eiffel parlance, only an "effective" class can be instantiated (it may be a descendant of a deferred class). A feature can also be deferred by using the <code>deferred</code> keyword in place of a <code>do</code> clause. If a class has any deferred features it must be declared as deferred; however, a class with no deferred features may nonetheless itself be deferred.
Deferred classes play some of the same role as [[interface (object-oriented programming)|interfaces]] in languages such as Java, though many object-oriented programming theorists believe interfaces are themselves largely an answer to Java's lack of multiple
===Renaming===
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 <code>rename</code> 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.
===
Tuples types may be viewed as a simple form of class, providing only attributes and the corresponding "setter" procedure. A typical tuple type reads
<syntaxhighlight lang="eiffel">
TUPLE [name: STRING; weight: REAL; date: DATE]
</syntaxhighlight>
and could be
<syntaxhighlight lang="eiffel">
["Brigitte", 3.5, Last_night]
</syntaxhighlight>
Components of such a tuple can be accessed as if the tuple tags were attributes of a class, for example if <code>t</code> has been assigned the above tuple then <code>t.weight</code> has value 3.5.
Line 186 ⟶ 283:
Thanks to the notion of assigner command (see below), dot notation can also be used to assign components of such a tuple, as in
<syntaxhighlight lang="eiffel">
t.weight := t.weight + 0.5
</syntaxhighlight>
The tuple tags are optional, so that it is also possible to write a tuple type as <code>TUPLE [STRING, REAL, DATE]</code>. (In some compilers this is the only form of tuple, as tags were introduced with the ECMA standard.)
The precise specification of e.g. <code>TUPLE [A, B, C]</code> is that it describes sequences of ''at least'' three elements, the first three being of types <code>A</code>, <code>B</code>, <code>C</code> respectively. As a result, <code>TUPLE [A, B, C]</code> conforms to (may be assigned to) <code>TUPLE [A, B]</code>, to <code>TUPLE [A]</code> and to <code>TUPLE</code> (without parameters), the topmost tuple type to which all tuple types conform.
===
Eiffel's "agent" mechanism wraps operations into objects.
For example, to execute the <code>my_action</code> block for each element of <code>my_list</code>, one would write:
<syntaxhighlight lang="eiffel">
my_list.do_all (agent my_action)
</syntaxhighlight>
To execute <code>my_action</code> only on elements satisfying <code>my_condition</code>, a limitation/filter can be added:
<syntaxhighlight lang="eiffel">
my_list.do_if (agent my_action, agent my_condition)
</syntaxhighlight>
In these examples, <code>my_action</code> and <code>my_condition</code> are routines. Prefixing them with <code>agent</code> 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 <code>a</code> represents that object (for example because <code>a</code> is the argument to <code>do_all</code>), the instruction
<syntaxhighlight lang="eiffel">
a.call ([x])
</syntaxhighlight>
will call the original routine with the argument <code>x</code>, as if we had directly called the original routine: <code>my_action (x)</code>. Arguments to <code>call</code> are passed as a tuple, here <code>[x]</code>.
Line 211 ⟶ 316:
It is possible to keep some arguments to an agent '''open''' and make others '''closed'''. The open arguments are passed as arguments to <code>call</code>: they are provided at the time of ''agent use''. The closed arguments are provided at the time of agent ''definition''. For example, if <code>action2</code> has two arguments, the iteration
<syntaxhighlight lang="eiffel">
my_list.do_all (agent action2 (?, y))
</syntaxhighlight>
iterates <code>action2 (x, y)</code> for successive values of <code>x</code>, where the second
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 <code>action2 (?, y)</code> with some operands closed and some open corresponds to a version of the original operation
The agent mechanism
<syntaxhighlight lang="eiffel">
appended:
</syntaxhighlight>
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:
<syntaxhighlight lang="eiffel">
my_list.for_all (agent (x: INTEGER): BOOLEAN do Result := (x > 0) end)
</syntaxhighlight>
The current agent mechanism leaves a possibility of run-time type error (if a routine with ''n'' arguments is passed to an agent expecting ''m'' arguments with ''m'' < ''n''). This can be avoided by a run-time check through the precondition <code>valid_arguments</code> of <code>call</code>. Several proposals for a purely static correction of this problem are available, including a language change proposal by Ribet et al.<ref>Philippe Ribet, Cyril Adrian, Olivier Zendra, Dominique Colnet: ''Conformance of agents in the Eiffel language'', in ''[[JOT: Journal of Object Technology|
===
A routine's result can be cached using the <code>once</code> keyword in place of <code>do</code>.
<syntaxhighlight lang="eiffel">
shared_object: SOME_TYPE
once
create Result.make (args)
-- This creates the object and returns a reference to it through `Result'.
end
</syntaxhighlight>
The returned object—<code>Result</code> in the example—can itself be mutable, but its reference remains the same.
Often "once routines" perform a required initialization: multiple calls to a
===
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:
: '''(Conversion principle) A type may not both conform and convert to another.'''
For example, <code>NEWSPAPER</code> may conform to <code>PUBLICATION</code>, but <code>INTEGER</code> converts to <code>REAL</code> (and does not inherit from it).
The conversion mechanism simply generalizes the ad hoc conversion rules (such as indeed between <code>INTEGER</code> and <code>REAL</code>) that exist in most programming languages, making them applicable to any type as long as the above principle is observed. For example, a <code>DATE</code> class may be declared to convert to <code>STRING</code>; this makes it possible to create a string from a date simply through
<syntaxhighlight lang="eiffel">
my_string := my_date
</syntaxhighlight>
as a shortcut for using an explicit object creation with a conversion procedure:
<syntaxhighlight lang="eiffel">
create my_string.make_from_date (my_date)
</syntaxhighlight>
To make the first form possible as a synonym for the second, it suffices to list the creation procedure (constructor) <code>make_from_date</code> in a <code>convert</code> clause at the beginning of the class.
Line 270 ⟶ 385:
As another example, if there is such a conversion procedure listed from <code>TUPLE [day: INTEGER; month: STRING; year: INTEGER]</code>, then one can directly assign a tuple to a date, causing the appropriate conversion, as in
<syntaxhighlight lang="eiffel">
Bastille_day := [14, "July", 1789]
</syntaxhighlight>
===
[[Exception handling]] in Eiffel is
<syntaxhighlight lang="eiffel">
server /= Void and then server.address /= Void
attempts:
server.connect
connected: server.is_connected
rescue
if attempts <
attempts := attempts + 1
end
end
</syntaxhighlight>
This example is arguably flawed for anything but the simplest programs, however, because connection failure is to be expected. For most programs a routine name like {{mono|attempt_connecting_to_server}} would be better, and the postcondition would not promise a connection, leaving it up to the caller to take appropriate steps if the connection was not opened.
===Concurrency===
A number of networking and threading libraries are available, such as EiffelNet and EiffelThreads. A concurrency model for Eiffel, based on the concepts of design by contract, is [[SCOOP (software)|SCOOP]], or ''Simple Concurrent Object-Oriented Programming'', not yet part of the official language definition but available in [[EiffelStudio]]. CAMEO<ref>{{cite journal|last=Brooke|first=Phillip|author2=Richard Paige|title=Cameo: An Alternative Model of Concurrency for Eiffel|journal=Formal Aspects of Computing|publisher=Springer|year=2008|doi=10.1007/s00165-008-0096-1|volume=21|issue=4|pages=363–391|s2cid=18336088|url=https://hal.archives-ouvertes.fr/hal-00534917/file/PEER_stage2_10.1007%252Fs00165-008-0096-1.pdf}}</ref> is an (unimplemented) variation of SCOOP for Eiffel. Concurrency also interacts with exceptions. Asynchronous exceptions can be troublesome (where a routine raises an exception after its caller has itself finished).<ref>{{cite journal|last=Brooke|first=Phillip|author2=Richard Paige|title=Exceptions in Concurrent Eiffel|journal=Journal of Object Technology|volume=6|issue=10|year=2007|url=http://www.jot.fm/issues/issue_2007_11/article4/|pages=111–126|doi=10.5381/jot.2007.6.10.a4|doi-access=free}}</ref>
===Operator and bracket syntax, assigner commands===
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 such as
<syntaxhighlight lang="eiffel">
a + b
</syntaxhighlight>
is conceptually understood as if it were
<syntaxhighlight lang="eiffel">
a.plus (b)
</syntaxhighlight>
with target <code>a</code>, feature <code>plus</code> and argument <code>b</code>.
Of course, the
<syntaxhighlight lang="eiffel">
plus alias "+" (other: INTEGER): INTEGER
-- ... Normal function declaration...
end
</syntaxhighlight>
The range of operators that can be used as "alias" is quite broad; they include predefined operators such as "+" but also "free operators" made of non-alphanumeric symbols. This makes it possible to design special infix and prefix notations,
Every class may in addition have ''one'' function aliased to "[]", the "bracket" operator, allowing the notation <code>a [i, ...]</code> as a synonym for <code>a.f (i, ...)</code> where <code>f</code> is the chosen function. This is particularly useful for container structures such as arrays, [[hash
<syntaxhighlight lang="eiffel">
number := phone_book ["JILL SMITH"]
</syntaxhighlight>
"Assigner commands" are a companion mechanism designed in the same spirit of allowing well-established, convenient notation reinterpreted in the framework of object-oriented programming. Assigner commands allow assignment-like syntax to call "setter" procedures. An assignment proper can never be of the form <code>a.x := v</code> as this violates information hiding; you have to go for a setter command (procedure). For example, the hash table class can have the function and the procedure
<syntaxhighlight lang="eiffel">
item alias "[]" (key: STRING): ELEMENT [3]
-- The element
do
... </syntaxhighlight>
Then to insert an element you have to use an explicit call to the setter command:
<syntaxhighlight lang="eiffel">
[4] phone_book.put (New_person, "JILL SMITH")
</syntaxhighlight>
It is possible to write this equivalently as
<syntaxhighlight lang="eiffel">
[5] phone_book ["JILL SMITH"] := New_person
</syntaxhighlight>
(in the same way that <code>phone_book ["JILL SMITH"]</code> is a synonym for <code>number := phone_book.item ("JILL SMITH")</code>), provided the declaration of <code>item</code> now starts (replacement for [3]) with
<syntaxhighlight lang="eiffel">
item alias "[]" (key: STRING): ELEMENT assign put
</syntaxhighlight>
This declares <code>put</code> as the assigner command associated with <code>item</code> and, combined with the bracket alias, makes [5] legal and equivalent to [4]. (It could also be written, without taking advantage of the bracket, as <code>phone_book.item ("JILL SMITH") := New_person</code>.
Note: The argument list of a's assigner is constrained to be: (a's return type;all of a's argument list...)
===Lexical and syntax properties===
Eiffel is not case-sensitive. The tokens <code>make</code>, <code>maKe</code> and <code>MAKE</code> all denote the same identifier. See, however, the "style rules" below.
Line 358 ⟶ 496:
The semicolon, as instruction separator, is optional. Most of the time the semicolon is just omitted, except to separate multiple instructions on a line. This results in less clutter on the program page.
There is no nesting of feature and class declarations. As a result, the structure of an Eiffel class is simple: some class-level clauses (inheritance, invariant) and a succession of feature declarations, all at the same level.
It is customary to group features into separate "feature clauses" for more readability, with a standard set of basic feature tags appearing in a standard order, for example:
<syntaxhighlight lang="eiffel">
class HASH_TABLE [ELEMENT, KEY -> HASHABLE] inherit
feature -- Initialization
-- ... Declarations of initialization commands (creation procedures/constructors) ...
feature -- Access
-- ... Declarations of non-Boolean queries on the object state, e.g. item ...
feature -- Status report
-- ... Declarations of Boolean queries on the object state, e.g. is_empty ...
feature -- Element change
-- ... Declarations of commands that change the structure, e.g. put ...
-- etc.
end
</syntaxhighlight>
In contrast to most [[curly bracket programming language]]s, Eiffel makes a clear distinction between expressions and instructions. This is in line with the [[Command-Query Separation]] principle of the Eiffel method.
===Style conventions===
Much of the documentation of Eiffel uses distinctive style conventions, designed to enforce a consistent look-and-feel. Some of these conventions apply to the code format itself, and others to the standard typographic rendering of Eiffel code in formats and publications where these conventions are possible.
While the language is case-insensitive, the style standards prescribe the use of all-capitals for class names (<code>LIST</code>), all-lower-case for feature names (<code>make</code>), and initial capitals for constants (<code>Avogadro</code>). The recommended style also suggests underscore to separate components of a multi-word identifier, as in <code>average_temperature</code>.
The specification of Eiffel includes guidelines for displaying software texts in typeset formats: keywords in bold, user-defined identifiers and constants are shown in ''<code>italics</code>'', comments, operators, and punctuation marks in <code>Roman</code>, with program text in <code>blue</code> as in the present article to distinguish it from explanatory text. For example, the "Hello, world!" program given above would be rendered as below in Eiffel documentation:
<syntaxhighlight lang="eiffel">
class
HELLO_WORLD
create
make
feature
make
do
print ("Hello, world!")
end
end
</syntaxhighlight>
===Interfaces to other tools and languages===
Eiffel is a purely object-oriented language but provides an [[open architecture]] for interfacing with "external" software in any other programming language.
It is possible for example to program machine- and operating-system level operations in [[C (programming language)|C]]. Eiffel provides a straightforward interface to C routines, including support for "inline C" (writing the body of an Eiffel routine in C, typically for short machine-level operations).
==
{{Reflist}}
==
*[http://www.eiffel.com/ Eiffel Software] web site of the company that introduced Eiffel, was Interactive Software Engineering (ISE).
*[https://www.liberty-eiffel.org/ LibertyEiffel] web site of the free GNU Eiffel development system.
{{Ecma International Standards}}
{{Authority control}}
{{DEFAULTSORT:Eiffel (Programming Language)}}
[[Category:Class-based programming languages]]
[[Category:Formal specification languages]]
[[Category:High-integrity programming languages]]
[[Category:Object-oriented programming languages]]
[[Category:Programming languages created in 1986]]
[[Category:Programming languages with an ISO standard]]
[[Category:Statically typed programming languages]]
|