JDK-6261279 : Variable number of generic parameters to a class
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-04-26
  • Updated: 2010-04-04
  • Resolved: 2008-05-20
In jga (http:/jga.sf.net), I'm forced to support several flavors of some of the key functors, with different numbers of generic parameters. For example, at this point there are three different forms of Constant -- as a Generator, a UnaryFunctor, and a BinaryFunctor.

I'd like to be able to get to having a single root Functor class that all specific functors derive from. I imagine the syntax would be

public class Functor<ReturnType, ArgType...> {
    public ReturnType exec(ArgType... args);

and the three main classes in jga would be

public class Generator<ReturnType>
        extends Functor<ReturnType>
    public ReturnType exec() { }

public class UnaryFunctor<ReturnType,ArgType>
        extends Functor<ReturnType,ArgType>
    public ReturnType exec(ArgType arg) { }

public class BinaryFunctor<ReturnType,Arg1Type,Arg2Type>
        extends Functor<ReturnType,Arg1Type,Arg2type>
    public ReturnType exec(Arg1Type arg1, Arg2Type arg2) { }

      The compiler would have to tie together the general varags placeholder in the set of generic parms with the overridden implementations, and enforce that the number and types as overridden are consistent with those declared in the basetype.

      A couple concrete examples:

public class Constant<ReturnType, ArgType...>
       extends Functor<ReturnType, ArgType...>
    private ReturnType r;
    public Constant(ReturnType r) { this.r = r; }

    public ReturnType exec(ArgType... args) { return r; }

      In this declaration, the ArgType... construct is repeated in the local class declaration, so that form is retained in the signature of the interface's method.

public class Less<ArgType>
        extends Functor<Boolean, ArgType, ArgType>
    public Boolean exec(ArgType arg1, ArgType arg2) {}

      In this form, the ArgType... construct is replaced with two instances of some type, so the interface method takes a pair of values of the parm type.

public class Foo
        extends Functor<Date, String, Point, Number...>
    public Date exec(String str, Point pt, Number... nums) {}

      It should work for more exotic combinations as well. I've been working on extending jga with VariableFunctors: it would allow the language parsed by the FunctorParser to contain any number of unknowns in the expressions rather that the 0, 1, or 2 that it is currently restricted to. Unfortunately, this will lead to still more duplicate implementations of a number of functors. In this case, generics is the root of the problem, and I might have to consider abandoning generics in the root functor implementations.

(see http://www.jroller.com/page/dhall/?anchor=generic_java_wishlist

This would allow generalization of functor interfaces via a single base functor implementation.  A number of commonly used functors have to be reproduced in each of several 'flavors' of functors, varying only in the number of generic parameters.

This would be very useful in the implementation of the feature requested in http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5061325
"Add language support for functors (function objects)", especially in response to the first

"Closures would be a huge win,, although I think the suggest approach is problematic and doesn't scale nicely to N-ary functions."

N-ary functors can't be supported with type-safety without some form of variable generic parm list.
###@###.### 2005-04-26 09:05:26 GMT

EVALUATION The difficulty of raising variable-arity expressions to variable-arity types comes in width subtyping. Consider class Foo<S,T...> {...} This defines a family of classes Foo<S> (for all S) with an infinite number of subfamilies Foo<S,T1>, Foo<S,T1,T2>, Foo<S,T1,T2,T3> etc. Foo<S> is logically a supertype of Foo<S,T1> - you would expect to be able to pass a Constant<String,Object> to a method which only wants a Functor<? extends String>. And Foo<S,T1> is a supertype of Foo<S,T1,T2>, and so on and so forth. Given final class Foo<S> today, there are no subtypes of Foo<Object>, but with final class Foo<S...> or final class Foo<S,T...>, there can be subtypes of Foo<Object>. The ability for a variable-arity type parameter to have zero type arguments is a problem. I suspect class Foo<S...> would be illegal because there would be no difference between the raw type Foo and the parameterized type Foo with zero type arguments. And this would be illegal because you don't know if there will be any S types to parameterize Foo with: class Bar<S...> extends Foo<S,T...> {...} This also implies any variable-arity type parameter could only be used as a variable-arity formal parameter in methods. With variable-arity types in generic classes would come calls for variable-arity types in generic methods, which will make type inference completely impossible to understand. (Variable-arity method invocation is bad enough.) There will be classfile format changes too. It is clear that the expressiveness gained by this RFE does not justify its complexity.

EVALUATION There is literally no end to the features people can suggest for Java. I don't see this as a high priority item. The time may come when it is plausible to act on this, however, so I'll leave this RFE open. ###@###.### 2005-04-26 17:17:36 GMT