Proposal: Access to Generic Type Parameters at Compile-Time
David Walend
david at walend.net
Tue Mar 24 05:41:25 PDT 2009
On Mar 23, 2009, at 1:44 AM, Joseph D. Darcy wrote:
> David Walend wrote:
>>
[snip]
>>
>> JDK5 Syntax -- three type specifiers, one of which requires the
>> developer to match the first two by hand:
>>
>> interface Path<Node,Edge,ThruGraph extends Digraph<Node,Edge>>
>> extends Digraph<Node,Edge>
>> {
>> Node getHead();
>> ...
>> }
>>
>
> [snip]
>
> When I see a Java type declared to have more than two type
> parameters my initial reaction is usually "this type isn't using the
> best decomposition of the problem space."
>
I agree. It's even worse when the type parameters layer on top of each
other.
These type parameters take effort to understand because they provide
no guidance to what is important. They are frustrating to drag through
the code to the compiler. When someone makes the effort to force a
system to work, whatever clarity could exist gets lost in the noise of
the resulting nested angle brackets. The entire complexity of the
problem is exposed in one declaration.
I have no doubt in my mind that a Path through a Digraph exists within
my mental context of that Digraph. The Path should use the same types
as the Digraph it traverses. It doesn't follow just any series of
alternating Nodes and Edges. Further, the Digraph should dictate types
to Paths for the Nodes and Edges when the Path is declared.
Part of the problem space is the tools available to solve the problem.
I mapped "dictating types" to generic type parameters, which resulted
in ugly, complex code. JDK5 generics provide two approaches when
generics begin to get complex: layered generics and wildcards. We are
already discussing layered generics. Wildcards work well when the type
doesn't matter -- when encapsulation and invisibility are total. I
found now way to use wildcards to say that two wildcard symbols must
be the same. JDK5 generics provides the two extremes of completely
hidden and completely exposed complexity, with no middle ground.
Java class structures provide a much richer set of options for member
variables and methods. Some details of a member variable's lifecycle
can be specified with final, transient and volatile. More importantly,
a member variable's accessibility can be public, protected, default or
private. One model of this proposal is that, before erasure, the type
parameters exist as final variables with the same visibility as the
declaration that contains them.
When a method has an unwieldy number of parameters, we'll often
refactor the code by creating a parameter object -- a class to contain
and replace all the parameters. A parameter object's members exploit
the final and accessibility keywords to act as a container of the
complexity.
When the code is compiled, type parameters are encapsulated but
unaccessible; JDK5 generics provide no access to type parameters
declared somewhere else. Implementing this proposal would give us that
access. In that sense, Semiring can play the role of a parameter
object for the type parameters that describe the problem domain.
This proposal would allow Path to be much cleaner -- just one type
parameter:
interface Path<ThruGraph extends Digraph>
Dave
David Walend
david at walend.net
More information about the coin-dev
mailing list