Parametrized method and cyclic inference
Remi Forax
forax at univ-mlv.fr
Sat Nov 3 11:08:34 PDT 2012
On 11/03/2012 06:40 PM, Dan Smith wrote:
> On Nov 2, 2012, at 6:27 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>>> Thanks! Feedback from real code is very useful.
>>>
>>> I'm confused about your emphasis on the implicit parameter type -- if your lambdas look like '(Integer x) -> 3', don't you still get an error?
>> No. Only, x -> 3 raises a cyclic inference error.
Hi Dan,
> I tried compiling this:
>
> Set<Mapper<Integer, Object>> set = Collections.singleton((Integer x) -> 3);
>
> And got an error:
>
> SingletonLambda.java:6: error: method singleton in class Collections cannot be applied to given types;
> Set<Mapper<Integer, Object>> set = Collections.singleton((Integer x) -> 3);
> ^
> required: T
> found: (Integer x)->3
> reason: cyclic inference - cannot infer target type for given lambda/method reference expression
> where T is a type-variable:
> T extends Object declared in method <T>singleton(T)
>
> This matches my expectation -- the compiler has to decide what the type of the lambda expression is before it looks at the target;
Yes, the idea is to enhance the existing inference algorithm to solve
the cyclic inference problems (at least some of them)
> there's no way to know that 'Mapper' is the intended type.
Look at the expected type on the right, as the target typing of lambda
does if it's an assignment and not a method call.
This works,
Mapper<Integer, Object> mapper = x -> 3;
but if you enclose the lambda in a parametrized method that takes a T
and return a T, a kind of identity on type,
the inference doesn't use the target type anymore.
I think this should be fixed, and as you said even if you type the
formal parameter of the lambda, it may still not work.
>
> So, are the use cases you're actually concerned about different than 'Collections.singleton'?
No, I've simplified the problem as said in my first mail. There are
several calls that takes a T and return a Foo of T in the code base,
I've summarized them by saying there are equivalent to
Collections.singleton().
It was a mistake as you demonstrate because the inference algorithm
works differently if T is bound by a function interface or not,
something I've not noticed until you mention it.
> Or are you mistaken about adding an explicit parameter type fixing the problem? Or maybe we're working with different compilers?
>
>>> Yes, #1 is hopeless -- there is no type anywhere to tell us what the lambdas represent.
>> I agree.
>> But what about, m((String x) -> 3, x -> 4),
>> i.e when on argument provide full types ?
> What is the type of the lambda expression? We'd have to pull a functional interface out of the air.
yes, right.
>
>>> How important are these use cases to you?
>> 17 out 23 usages of lambdas requires to declare parameters, it's perhaps just this codebase, but the question that comes in my mind is:
>> Is it a good idea to provide a special syntax (no need to declare parameter type in lambda) if this syntax can rarely be used ?
>
> Agreed; it is our intent that inference should be powerful enough to make explicit parameter types generally unnecessary. Any of your use cases that fail with implicit parameters but succeed with explicit parameters are examples of where the inference implementation likely needs to be improved.
>
> But I don't think 'singleton' falls into this category -- hence my question of whether use cases like 'singleton' are important. (More generally, I'm talking about methods that don't mention functional interfaces in their declarations.)
What your are suggesting, correct me if I'm wrong is instead of writing
<T> T foo(T element), I should write <T extends Runnable> T foo(T
element) for every function interfaces that exist ?
This seems to defeat the purpose of parametrized methods.
>
> —Dan
Rémi
More information about the lambda-spec-experts
mailing list