Tuples
This technical note is excerpted from the text of a proposal submitted
by ISE to the Nonprofit International Consortium for Eiffel (NICE). It
describes a set of extensions to Eiffel.
This is a working document, precise for the most part but informal in
places, and is currently under discussion.
The original form of this document was entitled Tuples, routine
objects and iterators and covered important applications of tuples.
These applications now have a detailed
discussion of their own. Make sure to read that discussion once you
have learned about tuples.
Because the note followed earlier discussions within the language
committee of NICE, it lacks the customary "introduction" and
"rationale" parts explaining the purpose of the proposed
extensions. The rationale and applications should, however, quickly become
clear to any reader familiar with Eiffel.
The mechanism described below is available in ISE Eiffel 4.3, with a
few limitations detailed below.
1. Tuple types
A new Kernel Library class is introduced: TUPLE.
Alone among all classes, class TUPLE
has a variable number of generic parameters. TUPLE,
TUPLE [X], TUPLE [X, Y], TUPLE [X,
Y, Z] and so on are all valid types, assuming valid
types X, Y, Z and so on.
Conformance rules:
[CONF1]
For n >= 0
TUPLE [U1, U2, ..., Un, Un+1] conforms to
TUPLE [U1, U2, ..., Un]
(and hence to TUPLE [T1,
T2, ..., Tn] if each
of the Ui
conforms to each of the Ti
for 1 <= i <= n.)
In particular all tuple types conform to TUPLE,
with no parameter.
[CONF2]
For n >= 0
If *every* one of the types T1, T2, ..., Tn conforms
to a type T, then TUPLE [T1, T2, ..., Tn] conforms
to ARRAY [T].
Definition: a "tuple type" is any type based on class TUPLE,
i.e. any type of the form TUPLE [T1,
T2, ..., Tn] for any n
(including 0, for which there is no generic parameter).
(Note 1: CONF1 should be understood in terms of the underlying
mathematical model. Mathematically, TUPLE [T1,
T2, ..., Tn] is the
set TUPLEn of all
partial functions f from N+ (the set
of non-negative integers) to T1 U
T2 U ... Tn,
such that:
-
The domain of f contains the
interval 1..n (in other words, f
is defined for any i such that 1
<= i <= n).
-
For 1 <= i <= n,
f (i) is a member of Ti.
With this definition, TUPLEn
is indeed a subset of TUPLEn+1,
and in particular TUPLE0,
the empty set, is a subset of TUPLEn
for any n.)
Semantics: an instance of TUPLE [T1,
T2, ..., Tn] is a tuple
whose first element is an instance of T1,
the second element being an instance of T2
etc. (The precise definition is the mathematical one given in note 1.)
Note that there can be more than n
elements to the tuple: for example a tuple with first element 5 and second
element "FOO" is an instance of all of the following tuple
types: TUPLE; TUPLE [INTEGER]; TUPLE
[INTEGER, STRING].
(Note 2: It may seem restrictive at first to permit only one class, TUPLE,
to have an arbitrary number of actual generic parameters. Why not have a
general mechanism for declaring any class C
so that all of C [X], C
[X, Y] etc. are valid? But in fact this is not
really a restriction. To obtain this effect without any complicated
language convention, just declare C as
C [G -> TUPLE]
and then use the generic derivations
C [TUPLE [X]]
C [TUPLE [X, Y]]
and so on. This also makes it possible to have the effect of some fixed
parameters and some variable ones, as in
C [G, H, I -> TUPLE]
so we have all the necessary flexibility.)
2. Tuple expressions
Let e1, e2, ..., en
be expressions of respective types T1,
T2, ..., Tn. Then the
expression
[e1, e2, ..., en]
denotes an instance of TUPLE [T1,
T2, ..., Tn], whose
first element is e1, the second element
being e2 etc.
Tuple expressions can be nested: whereas
[1, 2, 3]
is a tuple with three elements (representing an instance of TUPLE
[INTEGER, INTEGER, INTEGER]),
[1, [2, 3]]
is a tuple with two elements, the second one itself a tuple; the
overall expression represents an instance of TUPLE
[INTEGER, TUPLE [INTEGER, INTEGER].
As a special case of tuple expression syntax, the delimiters [
and ] are replaced by parentheses for the
tuple representing the actual argument list of a routine call (see section
4).
3. TUPLE features
The exact specification of class TUPLE
will be described in an addition to ELKS. The principal features are:
-
count (number of significant
elements)
-
item (i), with the obvious
precondition: the i-th element, of
type ANY (since the value of i
is not known at compile time); also first,
second, third,
fourth and fifth,
of the appropriate types.
-
put (x, i), with the
obvious precondition: replace i-th
element with x. If argument x
is not of the appropriate type Ti
there is no effect.
-
is_equal: redefined to consider only
the first n elements, where n
is the smaller length.
Other features under consideration include:
-
stripped (i): a tuple of type
TUPLE [T1, T2,
Ti-1, Ti+1, ..., Tn],
derived from the current one by removing the i-th component,
again with the obvious precondition.
-
wedged (x, i): a tuple
with one more element, inserted at position i.
-
infix "+": tuple
concatenation
-
infix "++": element
concatenation; t ++ x is the
same thing as t.wedged (x, t.count
+ 1).
In addition, there may be in class GENERAL
the following three features:
acceptable_tuple (t: TUPLE): BOOLEAN
-- Is t convertible into an object of the current
-- type?
associated_tuple: TUPLE
-- Tuple made of all of this object's field
ensure
acceptable_tuple (Result)
make_from_tuple (t: TUPLE)
-- Reset from t.
require
acceptable_tuple (t)
ensure
equal (associated_tuple, t)
4. What have we gained?
First we have solved the only case in the Eiffel language in which an
expression has no precisely defined type: polymorphic manifest arrays.
We don't have manifest arrays any more, but manifest tuples, with a
precisely defined type. No incompatibility is introduced thanks to rule
CONF2. The original syntax for manifest arrays, Result
:= <<e1, e2, ..., en>>,
will continue to be supported.
Second, we can define functions that return multiple results. This is
a quite significant increase in expressive power. No common language has
that. (You have to go to Lisp and functional languages.) Just define TUPLE
[...] as the result type; in the function, you will write things
like
Result := [e1, e2, ..., en]
Also, from a theoretical viewpoint, feature calls are simpler and
more homogeneous: every feature takes exactly one tuple as argument and
returns exactly one tuple as a result. (Either of these tuples may be
empty: the first for a feature with no argument, the second for a
procedure.) The syntax for a call becomes
Feature Arguments
with Arguments defined as
Tuple_expression
where the Tuple_expression uses the form
given in section 2 but with the outermost [ and ] delimiters replaced by
parentheses to conform to usual practice. So the call
f (a, b, c)
which we continue to think of as having three arguments a,
b and c, formally has only one tuple
argument [a, b, c]. This is of course not
to be confused with a call of the form
g ([a, b, c])
which has one argument (a tuple with three elements) in both the
ordinary and the formal sense.
5. Active, iterators, numerical applications, introspection
For a set of important applications of tuples see the book chapter on
agents and iterators which also covers aspects of numerical software
and related topics following from the tuple mechanism.
6. Temporary limitations
The implementation of tuples in ISE Eiffel 4.3 has the following
limitations:
-
Conformance of ARRAY types to TUPLE
types is not yet fully supported.
- Class TUPLE does not have features such
as first and second.
You must use item and, in most cases, an
assignment attempt.
|