ambiguous type inference while working with primitives

Brian Goetz brian.goetz at oracle.com
Thu May 10 08:09:07 PDT 2012


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
>
>
>
>


More information about the lambda-dev mailing list