Function type naming conventions

Brian Goetz brian.goetz at oracle.com
Wed Jan 2 11:23:05 PST 2013


Just to recap where we are in function type naming, we've got a few base 
types:

   Block<T>               T -> void
   Function<T,R>          T -> R
   Predicate<T>           T -> boolean
   Supplier<T>            () -> T

Plus some derived convenience types:

   UnaryOperator<T>       extends Function<T,T>
   BinaryOperator<T>      extends BiFunction<T,T,T>

We have arity prefixes to modify the natural arity of these:

   BiFunction<T,U,R>      (T,U) -> R
   BiPredicate<T,U>       (T,U) -> boolean

Presumably we'll be forced into TriXxx and worse at some point, but so 
far we've been able to avoid that.

We have a primitive specialization convention that lets you prefix 
{Int,Long,Double,Boolean} on front of one of these (possibly multiple 
times), and this gobbles the type argument that appears in the return 
position, or, if the return is not generic, the first type argument:

   IntFunction<T>         T -> int
   IntSupplier            () -> int
   IntBiFunction<T,U>     (T,U) -> int
   IntBinaryOperator      (int,int) -> int
   IntBlock               int -> void

So far we've got about 30 defined SAMs, and this has been mostly enough 
to implement our libraries, including primitive specializations.

This convention is an uneasy compromise that is part and parcel of the 
compromise/commitment we made to nominal function types.  Its a bit 
annoying in places, but the rules above are consistent, and the names 
read mostly reasonably in APIs, and better than most of the alternatives 
proposed, especially the fully general Function$FromIntAndDouble$ToDouble.

In fact, the only type we've come across repeatedly that wants a "nice" 
name that doesn't fit into the above scheme is:

   int -> T

which shows up in quite a few places.  There are probably a few others 
but this is the biggest.  (We also came across a desire for (T,int)->T 
in the reducer work, but that shows up in only one place.)

We could treat int -> R as a specialization of Function<T,R>, and extend 
the naming convention to handle it, or we could try to come up with a 
new top-level name for it.

In the latter category, IndexedSupplier<T> would work for some of the 
use cases (Arrays.fill, array suppliers) but not terribly well for 
IntStream.map(int -> T).

Other ideas?


More information about the lambda-libs-spec-experts mailing list