Parametrized method and cyclic inference
Remi Forax
forax at univ-mlv.fr
Fri Nov 2 17:27:51 PDT 2012
On 11/02/2012 11:19 PM, Dan Smith wrote:
> On Nov 2, 2012, at 10:48 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> Hi guys,
>> I've tried to take a big corpus of code and to refactor all inner-classes to use lambda instead.
>>
>> The good news is that on 23 uses of inner classes, 20 can be retrofited to use lambdas
>> because the target type is a SAM and they don't require a strong identity (this is not used).
>> The bad news is that among the 20 that can be retrofited, 17 can not be retrofited using
>> the syntax that doesn't specified the type of the formal parameter i.e. the natural syntax
>> because the compiler complains that there is a cyclic inference.
>>
>> The 17 snippets of code can be covered by 3 cases:
>> static <T> void m(T t1, T t2) {
>> // empty
>> }
>>
>> public static void main(String[] args) {
>> m(x -> 3, x -> 4); // case 1
>> Set<Mapper<Integer, Object>> set = Collections.singleton(x -> 3); // case 2
>> List<Mapper<Integer, Object>> list = Arrays.asList(x -> 1); // case 3
>> }
>>
>> To sumarrize, it's currently impossible to call a parametrized method with an untyped lambda,
>> the inference will just choke.
>>
>> I think instead that if there is a cyclic inference,
>> the return type should be used to try to infer the formal parameter type of the lambda,
>> at least, it will solve case 2 and 3.
> 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.
>
> 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 ?
>
> #2 and #3 are interesting. In general, we've nailed down a strategy for inference that depends on a target type. But this is special.
>
> The target type is an inference variable, T. Note that this is _not_ a functional interface. Everything we've done to this point has bailed out early if the target of a lambda is not a functional interface.
>
> An alternative would be to initially hope that T will be a functional interface, wait for T to be resolved, and then go from there. There are aspects of that that feel a little more complex than I would like, but it's probably doable.
>
> 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 ?
So I think these use cases are important if we want our users to be able
to use Arrays.asList(), Collections.addAll() or Collections.singleton*()
with a lambda as argument.
>
> —Dan
Rémi
More information about the lambda-spec-experts
mailing list