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