Comparator combinators

Brian Goetz brian.goetz at oracle.com
Wed Aug 14 12:49:45 PDT 2013


This may well be our last API loose end...

We currently have a pile of Comparator combinators, all currently called 
comparing() or thenComparing().  Regardless of whether we choose to go 
forward with the simplified overloading plan, these overloads have a 
problem: for implicit lambdas, we can't distinguish between

   comparing(T->U)
and
   comparing(T->int)

because we don't type-check the body of the lambda until we do overload 
selection, and don't do overload selection based on whether there are 
type errors in the body (this was roundly rejected as being too 
brittle).  So for lambdas like:

   comparing(x -> x.size())

we've got a circularity -- even under the older, more complex scheme.

We'd thought perhaps that, if we adopted the heuristic that we can 
eagerly give a type to method reference that refers to a non-overloaded 
method (e.g., Person::getAge), then cases like

   comparing(Person::getAge)

can be handled, and this might take some of the pressure off the problem.

For lambdas (with either approach) you can always get what you want with 
an explicit lambda:

   comparing((Person p) -> p.getAge())

since this can be type-checked early.

So the question is, is this good enough, even though it falls afoul of 
the overloading guidelines for implicit lambdas?  Or, should we mangle 
the names of the methods?

This question comes down to whether we think its better to force 
everyone to explicitly pick a method, but then supporting implicit lambdas:

   comparingInt(x -> x.size())

or forcing users to use non-ambigous method refs or explicit lambdas:

   comparing(Person::getAge)
or
   comparing((Person p) -> p.getAge())

Which disambiguation approach is worse?



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