diff --git a/documentation/current/method/eiffel-tutorial-et/et-design-contract-tm-assertions-and-exceptions.wiki b/documentation/current/method/eiffel-tutorial-et/et-design-contract-tm-assertions-and-exceptions.wiki
index bd240406..1d4b62ca 100644
--- a/documentation/current/method/eiffel-tutorial-et/et-design-contract-tm-assertions-and-exceptions.wiki
+++ b/documentation/current/method/eiffel-tutorial-et/et-design-contract-tm-assertions-and-exceptions.wiki
@@ -36,9 +36,9 @@ In addition to preconditions and postconditions, contract clauses include '''cla
==Expressing assertions==
-Eiffel provides syntax for expressing preconditions ( require ), postconditions ( ensure ) and class invariants ( invariant ), as well as other assertion constructs studied later (see [[10 Other Mechanisms|"Instructions", page 84]] ): loop invariants and variants, check instructions.
+Eiffel provides syntax for expressing preconditions ( require), postconditions ( ensure) and class invariants ( invariant), as well as other assertion constructs studied later (see [[10 Other Mechanisms|"Instructions", page 84]] ): loop invariants and variants, check instructions.
-Here is a partial update of class ACCOUNT with more assertions:
+Here is a partial update of class ACCOUNT with more assertions:
indexing
description: "Simple bank accounts"
@@ -84,13 +84,13 @@ invariant
end -- class ACCOUNT
-Each assertion is made of one or more subclauses, each of them a boolean expression (with the additional possibility of the old construct). The effect of including more than one sub clause, as in the postcondition of deposit and in the invariant, is the same as connecting them through an and . Each clause may be preceded by a label, such as consistent_balance in the invariant, and a colon; the label is optional and does not affect the assertion's semantics, except for error reporting as explained in the next section, but including it systematically is part of the recommended style. The value of the boolean expression a implies b is true except if a is true and b false.
+Each assertion is made of one or more subclauses, each of them a boolean expression (with the additional possibility of the old construct). The effect of including more than one sub clause, as in the postcondition of deposit and in the invariant, is the same as connecting them through an and. Each clause may be preceded by a label, such as consistent_balance in the invariant, and a colon; the label is optional and does not affect the assertion's semantics, except for error reporting as explained in the next section, but including it systematically is part of the recommended style. The value of the boolean expression a implies b is true except if a is true and b false.
Because assertions benefit from the full power of boolean expressions, they may include function calls. This makes it possible to express sophisticated consistency conditions, such as " the graph contains no cycle", which would not be otherwise expressible through simple expressions, or even through first-order predicate calculus, but which are easy to implement as Eiffel functions returning boolean results.
-The precondition of a routine expresses conditions that the routine is imposing on its clients. Here a call to deposit is correct if and only if the value of the argument is non-negative. The routine does not guarantee anything for a call that does not satisfy the precondition. It is in fact part of the Eiffel method that a routine body should '''never''' test for the precondition, since it is the client's responsibility to ensure it. (An apparent paradox of Design by Contract, which is reflected in the bottom-right entries of the preceding and following contract tables, and should not be a paradox any more at the end of this discussion, is that one can get more reliable software by having fewer explicit checks in the software text.)
+The precondition of a routine expresses conditions that the routine is imposing on its clients. Here a call to deposit is correct if and only if the value of the argument is non-negative. The routine does not guarantee anything for a call that does not satisfy the precondition. It is in fact part of the Eiffel method that a routine body should '''never''' test for the precondition, since it is the client's responsibility to ensure it. (An apparent paradox of Design by Contract, which is reflected in the bottom-right entries of the preceding and following contract tables, and should not be a paradox any more at the end of this discussion, is that one can get more reliable software by having fewer explicit checks in the software text.)
-The postcondition of a routine expresses what the routine guaranteed to its clients for calls satisfying the precondition. The notation old expression , valid in postconditions ( ensure clauses) only, denotes the value that expression had on entry to the routine.
+The postcondition of a routine expresses what the routine guaranteed to its clients for calls satisfying the precondition. The notation old expression, valid in postconditions ( ensure clauses) only, denotes the value that expression had on entry to the routine.
The precondition and postcondition state the terms of the contract between the routine and its clients, similar to the earlier example of a human contract:
{| border="1"
@@ -112,18 +112,18 @@ Update deposits list and balance.
No need to handle negative arguments.
|}
-The class invariant, as noted, applies to all features. It must be satisfied on exit by any creation procedure, and is implicitly added to both the precondition and postcondition of every exported routine. In this respect it is both good news and bad news for the routine implementer: good news because it guarantees that the object will initially be in a stable state, averting the need in the example to check that the total of all_deposits is compatible with the balance ; bad news because, in addition to its official contract as expressed by its specific postcondition, every routine must take care of restoring the invariant on exit.
+The class invariant, as noted, applies to all features. It must be satisfied on exit by any creation procedure, and is implicitly added to both the precondition and postcondition of every exported routine. In this respect it is both good news and bad news for the routine implementer: good news because it guarantees that the object will initially be in a stable state, averting the need in the example to check that the total of all_deposits is compatible with the balance; bad news because, in addition to its official contract as expressed by its specific postcondition, every routine must take care of restoring the invariant on exit.
-A requirement on meaningful contracts is that they should be in good faith: satisfiable by an honest partner. This implies a consistency rule: if a routine is exported to a client (either generally or selectively), any feature appearing in its precondition must also be available to that client. Otherwise -- for example if the precondition included require n > 0 , where n is a secret attribute -- the supplier would be making demands that a good-faith client cannot possibly check for.
+A requirement on meaningful contracts is that they should be in good faith: satisfiable by an honest partner. This implies a consistency rule: if a routine is exported to a client (either generally or selectively), any feature appearing in its precondition must also be available to that client. Otherwise -- for example if the precondition included require n > 0, where n is a secret attribute -- the supplier would be making demands that a good-faith client cannot possibly check for.
-Note in this respect that guaranteeing a precondition does not necessarily mean, for the client, testing for it. Assuming n is exported, a call may test for the precondition
+Note in this respect that guaranteeing a precondition does not necessarily mean, for the client, testing for it. Assuming n is exported, a call may test for the precondition
if x.n > 0 then x.r end
-possibly with an else part. But if the context of the call, in the client's code, implies that n is positive -- perhaps because some preceding call set it to the sum of two squares -- then there is no need for an if or similar construct.
+possibly with an else part. But if the context of the call, in the client's code, implies that n is positive -- perhaps because some preceding call set it to the sum of two squares -- then there is no need for an if or similar construct.
-{{note|In such a case, a check instruction as introduced later ( [[10 Other Mechanisms|"Instructions", page 84]] ) is recommended if the reason for omitting the test is non-trivial. }}
+{{note|In such a case, a check instruction as introduced later ( [[10 Other Mechanisms|"Instructions", page 84]] ) is recommended if the reason for omitting the test is non-trivial. }}
==Using contracts for built-in reliability==
@@ -135,7 +135,7 @@ This simple observation -- usually not clear to people until they have practiced
Contracts in Eiffel are not just wishful thinking. They can be monitored at run time under the control of compilation options.
-It should be clear from the preceding discussion that contracts are not a mechanism to test for special conditions, for example erroneous user input. For that purpose, the usual control structures ( if deposit_sum > 0 then ...) are available, complemented in applicable cases by the exception handling mechanism reviewed next. An assertion is instead a '''correctness condition''' governing the relationship between two software modules (not a software module and a human, or a software module and an external device). If sum is negative on entry to deposit , violating the precondition, the culprit is some other software element, whose author was not careful enough to observe the terms of the deal. Bluntly:
+It should be clear from the preceding discussion that contracts are not a mechanism to test for special conditions, for example erroneous user input. For that purpose, the usual control structures ( if deposit_sum > 0 then ...) are available, complemented in applicable cases by the exception handling mechanism reviewed next. An assertion is instead a '''correctness condition''' governing the relationship between two software modules (not a software module and a human, or a software module and an external device). If sum is negative on entry to deposit, violating the precondition, the culprit is some other software element, whose author was not careful enough to observe the terms of the deal. Bluntly:
{{note| '''Assertion Violation rule '''A run-time assertion violation is the manifestation of a bug. }}
@@ -147,26 +147,26 @@ To be more precise:
That violations indicate bugs explains why it is legitimate to enable or disable assertion monitoring through mere compilation options: for a correct system -- one without bugs -- assertions will always hold, so the compilation option makes no difference to the semantics of the system.
But of course for an incorrect system the best way to find out where the bug is -- or just that there is a bug -- is often to monitor the assertions during development and testing. Hence the presence of the compilation options, which EiffelStudio lets you set separately for each class, with defaults at the system and cluster levels:
-* no : assertions have no run-time effect.
-* require : monitor preconditions only, on routine entry.
-* ensure : preconditions on entry, postconditions on exit.
-* invariant : like ensure , plus class invariant on both entry and exit for qualified calls.
-* all : like invariant , plus check instructions, loop invariants and loop variants ( [[10 Other Mechanisms|"Exception handling", page 46]] ).
+* no : assertions have no run-time effect.
+* require : monitor preconditions only, on routine entry.
+* ensure : preconditions on entry, postconditions on exit.
+* invariant : like ensure, plus class invariant on both entry and exit for qualified calls.
+* all : like invariant, plus check instructions, loop invariants and loop variants ( [[10 Other Mechanisms|"Exception handling", page 46]] ).
An assertion violation, if detected at run time under one of these options other than the first, will cause an exception ( [[8 Design by Contract (tm), Assertions and Exceptions|"Instructions", page 84]] ). Unless the software has an explicit "retry" plan as explained in the discussion of exceptions, the violation will cause produce an exception trace and cause termination (or, in EiffelStudio, a return to the environment's browsing and debugging facilities at the point of failure). If present, the label of the violated sub clause will be displayed, to help identify the problem.
-The default is require . This is particularly interesting in connection with the Eiffel method's insistence on reuse: with libraries such as EiffelBase, richly equipped with preconditions expressing terms of use, an error in the '''client software''' will often lead, for example through an incorrect argument, to violating one of these preconditions. A somewhat paradoxical consequence is that even an application developer who does not apply the method too well (out of carelessness, haste, indifference or ignorance) will still benefit from the presence of contracts in someone else's library code.
+The default is require. This is particularly interesting in connection with the Eiffel method's insistence on reuse: with libraries such as EiffelBase, richly equipped with preconditions expressing terms of use, an error in the '''client software''' will often lead, for example through an incorrect argument, to violating one of these preconditions. A somewhat paradoxical consequence is that even an application developer who does not apply the method too well (out of carelessness, haste, indifference or ignorance) will still benefit from the presence of contracts in someone else's library code.
During development and testing, assertion monitoring should be turned on at the highest possible level. Combined with static typing and the immediate feedback of compilation techniques such as the Melting Ice Technology, this permits the development process mentioned in the section [[3 The Software Process in Eiffel|"Quality and functionality", page 10]] , where errors are exterminated at birth. No one who has not practiced the method in a real project can imagine how many mistakes are found in this way; surprisingly often, a violation will turn out to affect an assertion that was just included for goodness' sake, the developer being convinced that it could never "possibly" fail to be satisfied.
By providing a precise reference (the description of what the software is supposed to do) against which to assess the reality (what the software actually does), Design by Contract profoundly transforms the activities of debugging, testing and quality assurance.
-When releasing the final version of a system, it is usually appropriate to turn off assertion monitoring, or bring it down to the require level. The exact policy depends on the circumstances; it is a trade off between efficiency considerations, the potential cost of mistakes, and how much the developers and quality assurance team trust the product. When developing the software, however, you should always assume -- to avoid loosening your guard -- that in the end monitoring will be turned off.
+When releasing the final version of a system, it is usually appropriate to turn off assertion monitoring, or bring it down to the require level. The exact policy depends on the circumstances; it is a trade off between efficiency considerations, the potential cost of mistakes, and how much the developers and quality assurance team trust the product. When developing the software, however, you should always assume -- to avoid loosening your guard -- that in the end monitoring will be turned off.
==The contract form of a class==
-Another application of assertions governs documentation. Environment mechanisms, such as clicking the Form Contract icon in Eiffelstudio, will produce, from a class text, an abstracted version which only includes the information relevant for client authors. Here is the contract form of class ACCOUNT in the latest version given:
+Another application of assertions governs documentation. Environment mechanisms, such as clicking the Form Contract icon in Eiffelstudio, will produce, from a class text, an abstracted version which only includes the information relevant for client authors. Here is the contract form of class ACCOUNT in the latest version given:
indexing
description: "Simple bank accounts"
@@ -198,7 +198,7 @@ invariant
end -- class interface ACCOUNT
-The words interface class are used instead of just class to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
+The words interface class are used instead of just class to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
Compared to the full text, the Contract Form of a class (also called its "short form") retains all its interface properties, relevant to client authors:
* Names and signatures (argument and result type information) for exported features.
@@ -207,9 +207,9 @@ Compared to the full text, the Contract Form of a class (also called its "short
* Class invariant (same observation).
-The following elements, however, are not in the Contract Form: any information about non-exported features; all the routine bodies ( do clauses, or the external and once variants seen in [[5 The Static Picture: System Organization|"External software", page 16]] above and [[10 Other Mechanisms|"Once routines and shared objects", page 82]] below); assertion subclauses involving non-exported features; and some keywords not useful in the documentation, such as is for a routine.
+The following elements, however, are not in the Contract Form: any information about non-exported features; all the routine bodies ( do clauses, or the external and once variants seen in [[5 The Static Picture: System Organization|"External software", page 16]] above and [[10 Other Mechanisms|"Once routines and shared objects", page 82]] below); assertion subclauses involving non-exported features; and some keywords not useful in the documentation, such as is for a routine.
-In accordance with the Uniform Access principle (page [[6 The Dynamic Structure: Execution Model|19]] ), the Contract Form does not distinguish between attributes and argument-less queries. In the above example, balance could be one or the other, as it makes no difference to clients, except possibly for performance.
+In accordance with the Uniform Access principle (page [[6 The Dynamic Structure: Execution Model|19]] ), the Contract Form does not distinguish between attributes and argument-less queries. In the above example, balance could be one or the other, as it makes no difference to clients, except possibly for performance.
The Contract Form is the fundamental tool for using supplier classes in the Eiffel method. It enables client authors to reuse software elements without having to read their source code. This is a crucial requirement in large-scale industrial developments.
@@ -227,14 +227,14 @@ The Contract Form -- or its variant the Flat-Contract Form, which takes account
Another application of Design by Contract governs the handling of unexpected cases. The vagueness of many discussions of this topic follows from the lack of a precise definition of terms such as "exception". With Design by Contract we are in a position to be specific:
* Any routine has a contract to achieve.
* Its body defines a strategy to achieve it -- a sequence of operations, or some other control structure involving operations. Some of these operations are calls to routines, with their own contracts; but even an atomic operation, such as the computation of an arithmetic operation, has an implicit contract, stating that the result will be representable.
-* Any one of these operations may fail , that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a on-representable result).
+* Any one of these operations may fail, that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a on-representable result).
* The failure of an operation is an '''exception''' for the routine that needed the operation.
* As a result the routine may fail too -- causing an exception in its own caller.
Note the precise definitions of the two key concepts, failure and exception. Although failure is the more basic one -- since it is defined for atomic, non-routine operations -- the definitions are mutually recursive, since an exception may cause a failure of the recipient routine, and a routine's failure causes an exception in its own caller.
-Why state that an exception "may" cause a failure? It is indeed possible to "rescue" a routine from failure in the case of an exception, by equipping it with a clause labeled rescue , as in:
+Why state that an exception "may" cause a failure? It is indeed possible to "rescue" a routine from failure in the case of an exception, by equipping it with a clause labeled rescue, as in:
read_next_character (f: FILE) is
-- Make next character available in last_character.
@@ -255,9 +255,9 @@ read_next_character (f: FILE) is
end
-This example includes the only two constructs needed for exception handling: rescue and retry . A retry instruction is only permitted in a rescue clause; its effect is to start again the execution of the routine, without repeating the initialization of local entities (such as impossible in the example, which was initialized to False on first entry). Features failed and last_character are assumed to be attributes of the enclosing class.
+This example includes the only two constructs needed for exception handling: rescue and retry. A retry instruction is only permitted in a rescue clause; its effect is to start again the execution of the routine, without repeating the initialization of local entities (such as impossible in the example, which was initialized to False on first entry). Features failed and last_character are assumed to be attributes of the enclosing class.
-This example is typical of the use of exceptions: as a last resort, for situations that should not occur. The routine has a precondition, file.readable , which ascertains that the file exists and is accessible for reading characters. So clients should check that everything is fine before calling the routine. Although this check is almost always a guarantee of success, a rare combination of circumstances could cause a change of file status (because a user or some other system is manipulating the file) between the check for readable and the call to low_level_read_function . If we assume this latter function will fail if the file is not readable, we must catch the exception.
+This example is typical of the use of exceptions: as a last resort, for situations that should not occur. The routine has a precondition, file.readable, which ascertains that the file exists and is accessible for reading characters. So clients should check that everything is fine before calling the routine. Although this check is almost always a guarantee of success, a rare combination of circumstances could cause a change of file status (because a user or some other system is manipulating the file) between the check for readable and the call to low_level_read_function. If we assume this latter function will fail if the file is not readable, we must catch the exception.
A variant would be
@@ -275,9 +275,9 @@ rescue
end
-which would try again up to Max_attempts times before giving up.
+which would try again up to Max_attempts times before giving up.
-The above routine, in either variant, never fails: it always fulfills its contract, which states that it should either read a character or set failed to record its inability to do so. In contrast, consider the new variant
+The above routine, in either variant, never fails: it always fulfills its contract, which states that it should either read a character or set failed to record its inability to do so. In contrast, consider the new variant
local
attempts: INTEGER
@@ -291,27 +291,27 @@ rescue
end
-with no more role for failed . In this case, after Max_attempts unsuccessful attempts, the routine will execute its rescue clause to the end, with no retry (the if having no else clause). This is how a routine '''fails'''. It will, as noted, pass on the exception to its caller.
+with no more role for failed. In this case, after Max_attempts unsuccessful attempts, the routine will execute its rescue clause to the end, with no retry (the if having no else clause). This is how a routine '''fails'''. It will, as noted, pass on the exception to its caller.
-Such a rescue clause should, before terminating, restore the invariant of the class so that the caller and possible subsequent retry attempts from higher up find the objects in a consistent state. As a result, the rule for an absent rescue clause -- the case for the vast majority of routines in most systems -- is that it is equivalent to
+Such a rescue clause should, before terminating, restore the invariant of the class so that the caller and possible subsequent retryattempts from higher up find the objects in a consistent state. As a result, the rule for an absent rescue clause -- the case for the vast majority of routines in most systems -- is that it is equivalent to
rescue
default_rescue
-where procedure default_rescue comes from ANY , where it is defined to do nothing; in a system built for robustness, classes subject to non-explicitly-rescued exceptions should redefine default_rescue (perhaps using a creation procedure, which is bound by the same formal requirement) so that it will always restore the invariant.
+where procedure default_rescue comes from ANY, where it is defined to do nothing; in a system built for robustness, classes subject to non-explicitly-rescued exceptions should redefine default_rescue (perhaps using a creation procedure, which is bound by the same formal requirement) so that it will always restore the invariant.
-Behind Eiffel's exception handling scheme lies the principle -- at first an apparent platitude, but violated by many existing mechanisms -- that a routine should '''either succeed or fail'''. This is in turn a consequence of Design by Contract principles: succeeding means being able to fulfill the contract, possibly after one or more retry ; failure is the other case, which must always trigger an exception in the caller. Otherwise it would be possible for a routine to miss its contract and yet return to its caller in a seemingly normal state. That is the worst possible way to handle an exception.
+Behind Eiffel's exception handling scheme lies the principle -- at first an apparent platitude, but violated by many existing mechanisms -- that a routine should '''either succeed or fail'''. This is in turn a consequence of Design by Contract principles: succeeding means being able to fulfill the contract, possibly after one or more retry; failure is the other case, which must always trigger an exception in the caller. Otherwise it would be possible for a routine to miss its contract and yet return to its caller in a seemingly normal state. That is the worst possible way to handle an exception.
Concretely, exceptions may result from the following events:
-* A routine failure ( rescue clause executed to the end with no retry ), as just seen.
+* A routine failure ( rescue clause executed to the end with no retry), as just seen.
* Assertion violation, if for a system that runs with assertion monitoring on.
-* Attempt to call a feature on a void reference: x.f (...) , the fundamental computational mechanism, can only work if x is attached to an object, and will cause an exception otherwise.
+* Attempt to call a feature on a void reference: x.f (...), the fundamental computational mechanism, can only work if x is attached to an object, and will cause an exception otherwise.
* Developer exception, as seen next.
* Operating system signal:arithmetic overfolow; no memory available for a requested creation or clone -- even after garbage collection has rummaged everything to find some space. (But no C/C++-like "wrong pointer address", which cannot occur thanks to the statically typed nature of Eiffel.)
-It is sometimes useful, when handling exceptions in rescue clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class EXCEPTIONS , which provides queries such as exception , giving the code for the last exception, and symbolic names ( [[10 Other Mechanisms|"Constant and unique attributes", page 83]] ) for all such codes, such as No_more_memory . You can then process different exceptions differently by testing exception against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a rescue clause is usually a sign that the mechanism is being misused. Class EXCEPTIONS also provides various facilities for fine-tuning the exception facilities, such as a procedure raise that will explicitly trigger a "developer exception" with a code than can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
+It is sometimes useful, when handling exceptions in rescue clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class EXCEPTIONS, which provides queries such as exception, giving the code for the last exception, and symbolic names ( [[10 Other Mechanisms|"Constant and unique attributes", page 83]] ) for all such codes, such as No_more_memory. You can then process different exceptions differently by testing exception against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a rescue clause is usually a sign that the mechanism is being misused. Class EXCEPTIONS also provides various facilities for fine-tuning the exception facilities, such as a procedure raise that will explicitly trigger a "developer exception" with a code than can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
==Other applications of Design by Contract==
diff --git a/documentation/current/method/eiffel-tutorial-et/et-dynamic-structure-execution-model.wiki b/documentation/current/method/eiffel-tutorial-et/et-dynamic-structure-execution-model.wiki
index 62dc73de..e61edfe7 100644
--- a/documentation/current/method/eiffel-tutorial-et/et-dynamic-structure-execution-model.wiki
+++ b/documentation/current/method/eiffel-tutorial-et/et-dynamic-structure-execution-model.wiki
@@ -267,21 +267,29 @@ Following the principle of Uniform Access (mentioned earlier in the section ''Ob
In the case of a routine with arguments -- procedure or function -- the routine will be declared, in its class, as
-feature (formal1: TYPE1; ...)
+some_feature (formal_1: TYPE_1; ...)
do
...
end
-meaning that, at the time of each call, the value of each formal will be set to the corresponding actual ( formal1 to argument1 and so on).
+meaning that, at the time of each call, the value of each formal will be set to the corresponding actual (formal_1 to argument_1 and so on).
-In the routine body, it is not permitted to change the value of a formal argument, although it is possible to change the value of an attached object through a procedure call such as formal1.some_procedure ( ... ) .
+In the routine body, it is not permitted to change the value of a formal argument, although it is possible to change the value of an attached object through a procedure call such as formal_1.some_procedure ( ... ) .
==Infix and prefix notation==
Basic types such as INTEGER are, as noted, full-status citizens of Eiffel's type system, and so are declared as classes (part of the Kernel Library). INTEGER, for example, is characterized by the features describing integer operations: plus, minus, times, division, less than, and so on.
-With the dot notation seen so far, this would imply that simple arithmetic operations would have to be written with a syntax such as i.plus (j) instead of the usual i + j. This would be awkward. Infix and prefix features solve the problem, reconciling the object-oriented view of computation with common notational practices of mathematics. The addition function is declared in class INTEGER as
+With the dot notation seen so far, this would imply that simple arithmetic operations would have to be written with a syntax such as
+
+ i.plus (j)
+
+instead of the usual
+
+ i + j
+
+This would be awkward. Infix and prefix features solve the problem, reconciling the object-oriented view of computation with common notational practices of mathematics. The addition function is declared in class INTEGER as
infix "+" (other: INTEGER): INTEGER
do
@@ -289,11 +297,14 @@ infix "+" (other: INTEGER): INTEGER
end
-Such a feature has all the properties and prerogatives of a normal "identifier" feature, except for the form of the calls, which is infix, as in i + j , rather than using dot notation. An infix feature must be a function, and take exactly one argument. Similarly, a function can be declared as prefix "-" , with no argument, permitting calls of the form -3 rather than (3).negated .
+Such a feature has all the properties and prerogatives of a normal "identifier" feature, except for the form of the calls, which is infix, as in i + j , rather than using dot notation. An infix feature must be a function, and take exactly one argument. Similarly, a function can be declared as prefix "-" , with no argument, permitting calls of the form -3 rather than (3).negated .
Predefined library classes covering basic types such as INTEGER, CHARACTER, BOOLEAN, REAL, DOUBLE are known to the Eiffel compiler, so that a call of the form j + i, although conceptually equivalent to a routine call, can be processed just as efficiently as the corresponding arithmetic expression in an ordinary programming language. This brings the best of both worlds: conceptual simplicity, enabling Eiffel developers, when they want to, to think of integers and the like as objects; and efficiency as good as in lower-level approaches.
-Infix and prefix features are available to any class, not just the basic types' predefined classes. For example a graphics class could use the name infix "|-|" for a function computing the distance between two points, to be used in expressions such as point1 |-| point2 .
+Infix and prefix features are available to any class, not just the basic types' predefined classes. For example a graphics class could use the name infix "|-|" for a function computing the distance between two points, to be used in expressions such as
+
+ point1 |-| point2
+
==Type declaration==
@@ -412,7 +423,7 @@ To copy an object, use
which assumes that both x and y are non-void, and copies the contents of y's attached object onto those of x's. For expanded entities the effect is the same as that the of the assignment x := y.
-An operation performing similar duty to the copy is twin . The assignment
+An operation performing similar duty to copy is twin . The assignment
x := y.twin
@@ -427,7 +438,6 @@ So, assuming both entities of reference types and y not void, the a
To determine whether two values are equal, use the expression:
-
x = y
@@ -464,7 +474,7 @@ and test whether it is void through:
Note that the assignment, := , and the equality operators, =, ~, /~, and /= , are language constructions, whereas copy, twin, is_equal, and equal are '''library features''' coming from class ANY .
-Void is a language keyword with built-in functionality, but it is not harmful to think of Void as another feature declared in ANY , but with type of NONE, the "bottom" type.
+Void is a language keyword with built-in characteristics, but it is not harmful to imagine Void as another feature declared in class ANY, with type of NONE, the "bottom" type. This convenience allows any assignment of the for x := Void to be valid without any making exceptions to the type rules, regardless of the type of x .
Using the redefinition mechanisms to be seen in the discussion of inheritance, a class can redefine copy and is_equal to cover specific notions of copy and equality. The assertions will ensure that the two remain compatible: after x.copy (y) , the property x .is_equal (y) must always be true. The effect of twin will automatically follow a redefinition of copy, and equal will follow is_equal.
diff --git a/documentation/current/method/eiffel-tutorial-et/et-genericity-and-arrays.wiki b/documentation/current/method/eiffel-tutorial-et/et-genericity-and-arrays.wiki
index 9b2047e4..7ee6b327 100644
--- a/documentation/current/method/eiffel-tutorial-et/et-genericity-and-arrays.wiki
+++ b/documentation/current/method/eiffel-tutorial-et/et-genericity-and-arrays.wiki
@@ -22,7 +22,7 @@ Within the class text, feature declarations can freely use G even t
first: G
-- Value of first list item
- extend (val: G) is
+ extend (val: G)
-- Add a new item of value val at end of list
...
@@ -45,23 +45,23 @@ Genericity reconciles extendibility and reusability with the static type checkin
==Arrays==
-An example of generic class from the Kernel Library is ARRAY [ G ], which describes direct-access arrays. Features include:
-* put to replace an element's value, as in my_array. put ( val, 25 ) which replaces by val the value of the array entry at index 25.
-* item to access an entry, as in my_array. item ( 25 ) yielding the entry at index 25. A synonym is infix "@", so that you may also write more tersely, for the same result, my_array @ 25.
+An example of generic class from the Kernel Library is ARRAY [G], which describes direct-access arrays. Features include:
+* put to replace an element's value, as in my_array.put (val, 25) which replaces by val the value of the array entry at index 25.
+* item to access an entry, as in my_array.item (25) yielding the entry at index 25. A synonym is infix "@", so that you may also write more tersely, for the same result, my_array @ 25 .
* lower, upper and count: queries yielding the bounds and the number of entries.
-* The creation procedure make, as in create my_array. make ( 1, 50 ) which creates an array with the given index bounds. It is also possible to resize an array through resize, retaining the old elements. In general, the Eiffel method abhors built-in limits, favoring instead structures that resize themselves when needed, either from explicit client request or automatically.
+* The creation procedure make, as in create my_array.make (1, 50) which creates an array with the given index bounds. It is also possible to resize an array through resize, retaining the old elements. In general, the Eiffel method abhors built-in limits, favoring instead structures that resize themselves when needed, either from explicit client request or automatically.
-The comment made about INTEGER and other basic classes applies to ARRAY too: Eiffel compilers know about this class, and will be able to process expressions of the form my_array. put ( val, 25 ) and my_array @ 25 in essentially the same way as a C or Fortran array access -- my_array [ 25 ] in C. But it is consistent and practical to let developers treat ARRAY as a class and arrays as objects; many library classes in EiffelBase, for example, inherit from ARRAY. Once again the idea is to get the best of both worlds: the convenience and uniformity of the object-oriented way of thinking; and the efficiency of traditional approaches.
+The comment made about INTEGER and other basic classes applies to ARRAY too: Eiffel compilers know about this class, and will be able to process expressions of the form my_array.put (val, 25) and my_array @ 25 in essentially the same way as a C or Fortran array access -- my_array [25] in C. But it is consistent and practical to let developers treat ARRAY as a class and arrays as objects; many library classes in EiffelBase, for example, inherit from ARRAY. Once again the idea is to get the best of both worlds: the convenience and uniformity of the object-oriented way of thinking; and the efficiency of traditional approaches.
A similar technique applies to another Kernel Library class, that one not generic: STRING, describing character strings with a rich set of string manipulation features.
==Generic derivation==
-The introduction of genericity brings up a small difference between classes and types. A generic class C is not directly a type since you cannot declare an entity as being of type C: you must use some actual generic parameter T -- itself a type. C [ T ] is indeed a type, but class C by itself is only a type template.
+The introduction of genericity brings up a small difference between classes and types. A generic class C is not directly a type since you cannot declare an entity as being of type C: you must use some actual generic parameter T -- itself a type. C [T] is indeed a type, but class C by itself is only a type template.
-The process of obtaining a type C [ T ] from a general class C is known as a '''generic derivation'''; C [ T ] is a '''generically derived type'''. Type T itself is, recursively, either a non-generic class or again a generically derived type D [ U ] for some D and U, as in LIST [ ARRAY [ INTEGER ]].)
+The process of obtaining a type C [T] from a general class C is known as a '''generic derivation'''; C [T] is a '''generically derived type'''. Type T itself is, recursively, either a non-generic class or again a generically derived type D [U] for some D and U, as in LIST [ARRAY [INTEGER]].)
-It remains true, however, that every type is based on a class. The base class of a generically derived type C [ T ] is C.
+It remains true, however, that every type is based on a class. The base class of a generically derived type C [T] is C.