Parametrized method and cyclic inference
Dan Smith
daniel.smith at oracle.com
Sat Nov 3 13:43:45 PDT 2012
On Nov 3, 2012, at 12:08 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> 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)
Wait -- see your response above: "No. Only, x -> 3 raises a cyclic inference error." My example uses "(Integer x) -> 3".
Let me ask again: which, if any, errors are you able to fix by adding a parameter type? My expectation is "none of them," unless we're lumping together two different kinds of problems.
>> 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.
If I understand correctly, all of the errors you're citing can be described as "takes a T and return a Foo of T". That's the main thing I care about -- whether the method's parameter type is "T" (inferred to be a functional interface type) or "FunctionalInterface<T>".
> 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.
No, I'm tentatively saying this is a new problem we need to fix.
We've been actively working on a solution to 'Predicate<String> p = negate(x -> x.isEmpty())' -- methods that expect a parameterization of a functional interface, and need to infer the parameters from the target type. I'm trying to decide whether your examples fit this description, or whether we need to do some new work which will handle things like 'Set<Predicate<String>> s = singleton(x -> x.isEmpty())'. My impression is that, yes, we need to handle this case too, but the comments you made about explicit vs. implicit parameters made me uncertain about this impression.
—Dan
More information about the lambda-spec-observers
mailing list