Path: utzoo!attcan!uunet!lll-winken!xanth!ames!ucsd!ucsbcsl!eiffel!bertrand From: bertrand@eiffel.UUCP (Bertrand Meyer) Newsgroups: comp.lang.eiffel Subject: Multi-branch instructions and unique values (Version 2.2 preview) Keywords: Case, Enumeration Message-ID: <122@eiffel.UUCP> Date: 19 Mar 89 04:33:29 GMT Organization: Interactive Software Engineering, Santa Barbara CA Lines: 219 Version 2.2 of Eiffel includes two new facilities for multi-branch choices. The following is extracted from an internal document describing the purpose and form of these extensions and (under suitable form) will be found in the documentation for the new release. It seemed that readers of this news group would be interested in seeing an advance version. ------------------- CUT HERE ---------------------------------- MULTI-BRANCH CHOICES IN EIFFEL Bertrand Meyer February 21, 1989 (Edited for posting to Usenet, March 18) 1 Overview ---------- The introduction of a ``test'' instruction and of a ``unique'' form of constant attribute declaration is meant to enable programmers to write simple multi-branch choices. The extension is purposely simple and limited. Advanced cases of multi-branch discriminations should be handled not by a test instruction (the equivalent of Pascal's or Ada's case instruction) but by using redefined routines and dynamic binding. Dynamic binding ensures openness by making it possible to add new cases at any time without disrupting the structure of existing software. In contrast, test or case instructions are closed: they specify a fixed set of choices. They may be needed, however, in simple cases of choosing between a set of fixed alternatives. For this reason, there was no form of case instruction in Eiffel until version 2.1. Although it came as a shock to some users, this absence was not a major problem in actual use of Eiffel once the inheritance techniques had been understood. One user remarked that ``not having a case instruction for six months was excellent for new object-oriented programmers''. Once the concepts have been understood, however, there remain situations in which a simple multi-branch instruction is needed. These include straightforward discriminations between a fixed set of cases, where the context does not justify introducing one heir class per case, and discriminating between ASCII characters on input. The design reported here and implemented for version 2.2 of Eiffel addresses these cases. The resulting constructs should be used with reason; great care should be taken not to destroy the openness of object-oriented structures, which is such a key factor in the extendibility and the reusability obtained through proper application of the object-oriented method. In designing these constructs, it was strongly felt that the extension should remain modest, and should not introduce any fundamentally new concept. In particular, no new data type is involved; no ``literal'' type is needed in Eiffel. The extension involves two simple concepts: + A new form of constant value, written unique, making it possible to define constant attributes whose values are chosen by the compiler, not by the programmer. + A new control structure, test... end, similar to Pascal's case instruction. 2 Multi-branch choices in current Eiffel ---------------------------------------- In Eiffel version 2.1, as described in the book ``Object-Oriented Software Construction'', a multi-branch choice can be implemented as an if... then... else... instruction: if e = v1 then i1 elsif e = v2 then i2 ... elsif e = vn then in This works but has two disadvantages: + Performance: when the values v1, v2 etc. are consecutive integer or character values, the implementation cannot easily take advantage of the well- known constant-time ``jump table'' technique; instead, tests must be performed sequentially. + Convenience: It is often the case that the values v1, v2 are symbolic constants, whose value is not meaningful as long as all values are different. This is handled in Pascal or Ada by defining these values as leterals. In current Eiffel, the constants must be declared individually and their values chosen explicitly by the programmer, as in blue: INTEGER is 1; white: INTEGER is 2; red: INTEGER is 3; ... This is tedious. The design described below removes these limitations. This is its sole aim; it should be viewed as a mechanism to improve the performance and convenience of the current Eiffel techniques, NOT AS A NEW TECHNIQUE. No conceptually new technique is needed here, only existing techniques made simpler to use. 3 ``Unique'' constants ---------------------- The value of a constant integer attribute may now be declared not just as a literal value (such as, say, 347) but as ``unique'' (``unique'' is a new keyword). For example: blue: INTEGER is unique; white: INTEGER is unique; red: INTEGER is unique; A ``unique'' value is chosen by the compiler; all attributes declared as ``unique'' within a class are uaranteed to have different values, hence the name. No further property is guaranteed to hold of these values; programmers have no control over the policy used by the compiler to assign ``unique'' values. Uniqueness of values is guaranteed within each class; ``unique'' entities declared in different classes, whether or not they are related by inheritance, are not guaranteed to have different values. Only integer constants may be declared as ``unique''. As a notational facility, two or more ``unique'' declarations may be grouped, as in blue, white, red: INTEGER is unique; The meaning of such a combined declaration is the same as if the declarations had been written separately as above. 4 The ``test'' instruction -------------------------- The test instruction is written as follows: test e when v11, v12, ... then instructions when v21, v22, ... then instructions ... when vn1, vn2, ... then instructions end In this notation: e is an expression of type INTEGER or CHARACTER; v11, v21, ..., v21, etc., called ``test constants'' in the sequel, are constants of the same type as e; instructions represents a sequence of zero or more instruction separated by semicolons. The test constants may be explicit constant values or constant attributes; in the latter case they may have been declared as ``unique''. The following rules apply to the set of test constants: + If any of these constants are declared as ``unique'', then all of them must be so declared; furthermore, they must have all been declared IN THE SAME CLASS. (This means REALLY in the same class: in particular, it is not permitted to have some of them declared in a class and some coming from proper ancestors of that class.) + If the test constants are not declared as ``unique'', that is to say if they have explicit values, then all of these values must be different. For test constants declared explicitly (not ``unique''), a notational facility is offered: a sequence of consecutive explicit values, such as 3, 4, 5 or 'a', 'b', 'c', 'd' may be abbreviated as an interval, written in the form min..max, as in one of the following: 3..5 'a'..'d' The effect of a test instruction of the above form is defined as follows. The value of e is computed. By the above rules, there can be at most one ``when'' branch such that one of its test values (after expansion of any intervals) is equal to the value of e. If this is the case, the corresponding ``then'' clause is executed and this terminates the execution of the test instruction. If no test value is equal to the value of e, an exception is raised. The symbolic name for the corresponding exception code in the library class EXCEPTIONS is Invalid_test_value. It is important to note that the test instruction has no ``else'' clause or equivalent, and that its effect if none of the test values matches that of the expression is NOT to execute an empty operation but to trigger an exception. The test instruction (as its Pascal and Ada counterparts) is potentially dangerous because it reflects the programmer's expectation that the value of e will be one of the stated test values. The least we can expect from the programmer is that he precisely specify what these expected values are. If at run-time the expression does not evaluate to any of these, then this is a serious abnormal case that should be detected immediately, not quietly ignored.