ambiguous type inference while working with primitives

Jim Gish jim.gish at oracle.com
Fri May 11 07:54:26 PDT 2012


On 05/10/2012 11:09 AM, Brian Goetz wrote:
> A few comments on this:
>
> 1.  I think we have a solution in the works for the ambiguity problem 
> you ran into, but it is not yet implemented.  So, stay tuned.
>
> 2.  The fused operations mapReduce may go away.  These fused ops exist 
> only as a workaround for the pain of reducing over unnecessarily boxed 
> values (think: mapReduce(String::length, Integer::plus)).  The library 
> can fuse map/reduce even without a fused method, so this is entirely 
> about boxing.  When we figure out the primitives story, this methods 
> may or may not go away.
>
> 3.  To answer your question: if you want to force a particular 
> overload resolution, cast one or more lambda to the appropriate SAM 
> type, such as
>
>   mapReduce( (DoubleMapper) ..., (DoubleBinaryOperator) ...)
>
> On 5/9/2012 3:39 PM, Jim Gish wrote:
>> On 03/06/2012 06:44 PM, maurizio cimadamore wrote:
>>> Hi
>>> This error occurs because you have two applicable methods, namely:
>>>
>>> *) comparing(IntMapper)
>>>
>>> *) comparing(LongMapper)
>>>
>>> When there are multiple applicable methods, the compiler tries to
>>> disambiguate the call-site using a routine called most-specific. The
>>> goal is to look at the two ambiguous signatures and see if one can be
>>> considered 'more specific' than the other. For instance, if you have 
>>> two
>>> applicable methods, one accepting an Object, and the other accepting an
>>> Integer, the latter would 'win' as Integer is a subtype of Object.
>>>
>>> What's happening in this case is that the compiler doesn't have enough
>>> information to disambiguate the call-site by just looking at the method
>>> signatures - that's because IntMapper and LongMapper are two unrelated
>>> types, so the compiler doesn't know which method to pick - hence the
>>> ambiguity error.
>>>
>>> We are currently exploring the design space, to see if we can allow 
>>> some
>>> restricted form of structural subtyping in the most specific algorithm
>>> (this would allow, i.e. to prefer IntMapper to LongMapper because the
>>> return type of the IntMapper's descriptor is more specific).
>>>
>>> Maurizio
>>>
>>> On 06-Mar-12 8:51 PM, Antoras wrote:
>>>> I get compiler errors due to ambiguous Mapper-objects. I have a class
>>>> Person which has a method getAge(). If the return value of this method
>>>> is 'int' the following inline Mapper-object produces an error:
>>>>
>>>> Comparator<Person>    c = comparing((Person p1) ->    p1.getAge());
>>>>
>>>> If the return type is 'Integer' the above code works.
>>>>
>>>> This line:
>>>>
>>>> Comparator<Person>    c = comparing(Person::getAge);
>>>>
>>>> works neither with 'Integer' nor with 'int';
>>>>
>>>> Is this expected behavior or should the type checker recognize that
>>>> IntMapper is the first one to "choose"?
>>>>
>>>>
>>>> The error message:
>>>>
>>>> ListTest.java:203: error: reference to comparing is ambiguous, both
>>>> method<T#1>comparing(LongMapper<T#1>) in Comparators and method
>>>> <T#2>comparing(IntMapper<T#2>) in Comparators match
>>>>         Comparator<Person>    c = comparing((Person p1) ->    
>>>> p1.getAge());
>>>>                                ^
>>>>       where T#1,T#2 are type-variables:
>>>>         T#1 extends Object declared in 
>>>> method<T#1>comparing(LongMapper<T#1>)
>>>>         T#2 extends Object declared in 
>>>> method<T#2>comparing(IntMapper<T#2>)
>>>>
>>>
>> I think I have the same problem here:
>>
>>      StringJoinerTest.java:46: error: reference to mapReduce is
>>      ambiguous, both method mapReduce(LongMapper<? super
>>      T>,long,LongBinaryOperator) in Iterable and method
>>      mapReduce(DoubleMapper<? super T>,double,DoubleBinaryOperator) in
>>      Iterable match
>>               int altCompOfStringsLength = lastNames.mapReduce( e ->
>>      e.length(), 0, (a, b) ->  a+b);
>>                                                     ^
>>         where T is a type-variable:
>>           T extends Object declared in interface Iterable
>>      1 error
>>
>> So, how does one go about disambiguating this, other than breaking out
>> the lambda expressions (and somewhat defeating the point of the
>> compactness value).  This, for example, works:
>>
>>           int stringsLength = lastNames.map(e ->  e.length()).reduce(0,
>> (a, b) ->  a+b);
>>
>> Thanks,
>>      Jim
>>
>>
>>
>>
Maurizio's fix solved my problem.  (Thanks for the quick fix 
Maruizio!).  I thought I tried the casting and was getting a different 
compile error.  I'll have to go back and check.



More information about the lambda-dev mailing list