Generic creation
This technical note describes the mechanism for creating objects
of formal generic types, as present in ISE Eiffel release
4.3. With the exception of an added Overview (section 1 below),
it is identical to the text of a language extension
proposal submitted by ISE to the Nonprofit International Consortium for
Eiffel (NICE).
Note that the examples use the new syntax for creation instructions
which is intended to replace the classical
create x. Both forms will continue
to be supported for several years.
All page numbers refer to the current definition of Eiffel:
the book Eiffel: The Language.
1. Overview
The problem addressed by this extension is simple: how to create an
object of a type known only through a formal generic parameters.
In a class C [G], you may have declared x of type G, and want
to execute a creation instruction
for some creation procedure
make of your choice.
For this to be type-safe, however, we need to know a little more
about G, since in the most general case it represents
an arbitrary type, so we have no clue about what kind of
creation procedure it may require if any, and with what arguments.
For this reason such creation instructions have been prohibited
in Eiffel until now. You had to encapsulate the creation in a
procedure on the client side (where the actual generic parameter
is known -- separately for each client).
The new mechanism removes this limitation, due to the following
elegant idea (credit for which is entirely due to Mark Howard
from Axa Rosenberg, formerly Rosenberg Institutional Equity Management).
It is based on the Eiffel technique of constrained genericity.
To guarantee that the above creation instruction is valid,
just make sure that G is a
constrained generic parameter, with a
class declaration of the form
class C
[G -> CONSTRAINT
create make, ... end] ...
listing make
as one of the applicable creation procedures.
The rules are that
make must be a procedure of the constraining type, CONSTRAINT,
with of course the right argument types.
When you use a generic derivation C [T], where type
T must conform to CONSTRAINT, the version of make
in T (possibly renamed, redefined etc.) must be listed as a
creation procedure for T.
This ensures type safety.
The beauty of the scheme is that make,
or any of the other creation procedures used for entities of type
G, does not need to be a creation procedure in CONSTRAINT;
it simply needs to be a procedure with the appropriate arguments.
Only for descendants of CONSTRAINT used as actual generic
parameters does it matter that make be a creation procedure.
This allows in particular CONSTRAINT to be a deferred class.
This overview should be sufficient to any Eiffel user desiring to
use the mechanism. The detailed specification follows.
2. Syntax
The production for Constraint, on page 201, which reads
Constraint == "->" Class_type
becomes
Constraint == "->" Class_type [Creation_constraint]
with (see page 285)
Creation_constraint == create Feature_list end
Note: in the syntax for Creators, page 285,
the keyword creation will be replaced by create for simplicity. (The
older keyword will continue to be accepted by compilers.)
3. Validity
New validity rule VTCC, page 201:
A Constraint is valid if and only if every identifier listed
in the Feature_list of its Generic_creators, if any, is the name
of a procedure of the base class of its Creator_type.
Adaptation of VTCG, page 203 (with clause 3 already adapted for
the "Generics in Constraints" change) now reads:
Let C be a constrained generic class. A Class_type CT having
C as base class is valid if and only if
CT
satisfies the
Unconstrained Genericity rule (VTUG, page 201) and in addition,
for any Formal_generic parameter G in the declaration of C
having a constraint, then if D is the Class_type listed in
the constraint and T, with base class BT, is the Type
corresponding to G in the Actual_generics list of CT:
3. T conforms to the type obtained from D by substituting
any occurrence of a formal generic parameter of C by the
corresponding actual parameter.
4. If the constraint for G has a Generic_creators part,
then the C version of every procedure of
BT listed (as
per rule VTCC, page 201) in that part is declared in BT
as a creation procedure.
In VGCC, page 286, replace clause 1 by
If T is a Formal_generic_name (that is to say, a formal
parameter of the class where the instruction appears), then
the corresponding formal generic parameter has a Constraint
part with a Generic_creators part, and the creation instruction
has a Creators part whose feature is one of the procedures
listed (as per rule VTCC, page 201) listed in the Generic_creators
part. Cases 2 to 6 assume that T is not a Formal_generic_name.
4. Semantics
The semantics of a creation call of the form
create x.proc (arguments)
where the type of x is (as per VGCC (1)) a formal generic parameter
with a constraint listing proc in its Generic_creators part,
is to create an object of the type T used as the corresponding actual
generic şarameter in the generic derivation considered, using
as creation procedure the version of proc in the base class
BT of T. As per VGCC (3), BT must declare that version as a creation
procedure.
|