Comparators.comparing overloads
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jul 22 02:28:57 PDT 2013
On 21/07/13 22:25, Sam Pullara wrote:
> I agree that this seems pretty broken to me.
>
> comparingInt
> comparingDouble
> comparingLong
>
> seem necessary to avoid this error:
>
> java: reference to comparing is ambiguous
> both method <T>comparing(java.util.function.ToLongFunction<? super T>) in java.util.Comparator and method <T>comparing(java.util.function.ToDoubleFunction<? super T>) in java.util.Comparator match
This problem has been discussed before - the current status quo of the
structural most specific comparison beween different functional
descriptors can only kick in when the parameter types of two functional
descriptors are the same (this is a sensible rule - as you can compare
meaning of an implicit lambdas type-checked against different target
types only if the inferred parameter types are equal in both cases -
which means semantics of the body doesn't change).
We are working on an improvement over current strategy that will handle
cases like this; the improvement consists in reusing inference
information from most specific, so that the structural most specific
check will now kick in also when two sets of functional descriptor
parameter types are _inferred_ to be equal.
Note that when the condition is not satisfied, all bets are off and the
compiler doesn't even bother to look at the shape of the function
descriptors - that's why all calls are judged ambiguous.
Maurizio
>
> Even stranger to me is that it doesn't even mention the correct one:
>
> public static <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor)
>
> Good explanation for that?
>
> Currently you need to write this code like:
>
> Comparator<String> comparator = Comparator.comparing((ToIntFunction<String>) String::length);
>
> Which seems strange when I imagine this is a common case.
>
> Sam
>
> On Jul 21, 2013, at 2:16 PM, Richard Warburton <richard.warburton at gmail.com> wrote:
>
>> Hi,
>>
>> We only mangle the name for return types, not argument types.
>> Thanks for the prompt reply.
>>
>> Things still seem a little messy in this situation though. Perhaps I've
>> missed something but we're talking about needing a cast for
>> any keyExtractor function that returns a number. That seems to be a fairly
>> common scenario for a keyExtractor. Suppose I want to sort Strings by
>> length, and I want to write:
>>
>> Comparator<String> comparator = comparing(String::length);
>>
>> I'll get an error telling me that the "reference to comparing is
>> ambiguous". Now in fact I can't even hint to the compiler using a return
>> type cast as with the following snippet:
>>
>> Comparator<String> comparator = comparing(str -> (int) str.length());
>>
>> I presume this is because a cast to int can auto-box to Integer which
>> subtypes Object, so its still ambiguous between Function and ToIntFunction.
>> Again, perhaps I've missed something here, but the way to get around this
>> issue is by providing an explicit type for the keyExtractor function:
>>
>> ToIntFunction<String> lengthOfString = String::length;
>> Comparator<String> comparator = comparing(lengthOfString);
>>
>> Which really does seem less elegant to me than having overloads with
>> mangled names. As I say this isn't a weird corner case - numbers are an
>> obvious thing to use as a comparator key.
>>
>> regards,
>>
>> Dr. Richard Warburton
>>
>> http://insightfullogic.com
>> @RichardWarburto <http://twitter.com/richardwarburto>
>>
>
More information about the lambda-dev
mailing list