Overload resolution simplification

Zhong Yu zhong.j.yu at gmail.com
Sat Aug 10 11:09:07 PDT 2013


On Sat, Aug 10, 2013 at 12:41 PM, maurizio cimadamore
<maurizio.cimadamore at oracle.com> wrote:
> On 10-Aug-13 5:50 PM, Zhong Yu wrote:
>>
>> I'd appreciate that very much! The map() overloading use case wouldn't
>> be rare in practice. People will feel bad if javac cannot see that the
>> lambda parameter type is obviously fixed.
>
> While I'm sympathetic with this position, this would mean that stuff like
>
> IntStream map(IntFunction<T>)
> <Z> Stream<Z> map(Function<T, Z>)
>
> map(x->1);
>
> would work, while the following 'static' variant:
>
> <U> IntStream map(Stream<U> s, IntFunction<U>)
> <U, V> Stream<V> map(Stream<U>, Function<U, V>)
>
> Stream<String> ss = ...
> map(ss, x->1);
>
> Would _not_ work. And it feels a bit weird - if the first case is deemed
> important, the second is equally important - it's just same example in a
> different style.

Probably not equally important in practice. We've seen quite a few
uses cases of the 1st form, but not of the 2nd.

Will it do more harm to allow 1st and disallow 2nd, because of the
confusion it causes? I think not.

The people affected are mostly API designers, not API users. They are
fewer in number, and presumably more knowledgeable. If they are
surprised that the 2nd form of overload doesn't work well, that is
bad, but not as bad as depriving them of the 1st form of overload.


>
> Then I guess next step would be to say - obviously javac can see what 'U' is
> by looking at the input stream. Which is essentially where we were: in this
> case instantiating U is fine but there are cases (Comparators.comparing)
> where it's not ok. And it seems like not everybody is comfortable in making
> those subtle distinctions.
>
> It's obviously a problem of 'where to draw the line'. But there are
> advantages in scaling back a bit and give up a bit of expressiveness as the
> model you get is much simpler to explain and so are its boundaries. This
> property is not to be underestimated.
>
> Note that the 'same parameter' rule you are advocating for requires global
> reasoning: to see whether a lambda can be type-checked you have to consider
> all matching signatures and see if they impose same parameter on the
> implicit lambda. This can be trivial to see in simple examples (such as map)
> - but what if the example is more convoluted? I.e. many overloads? Or
> different sam types using different ordering for type parameters i.e.
>
> Function1<X, Y> {
>    Y apply(X x)
> }
>
>
> Function2<X, Y> {
>    X apply(Y x)
> }

I don't understand this one, can you give an example?

>
> I believe that in such cases (or even more complex ones with nested SAM
> types as type-parameters) we'll be essentially at compiler's mercy - i.e. it
> would be very hard to judge whether a method call would succeed w/o trying
> it first on javac. And that's bad too.

I agree, but Java has passed that point. Most programmers have trouble
dealing with generics.

>
> Maurizio


More information about the lambda-spec-observers mailing list