SAM conversion of inlined lambda expression

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Aug 25 07:50:32 PDT 2010


On 25/08/10 15:29, Thomas Jung wrote:
> Well, actually it works. But only for types that do not need unboxing,
> I suppose, as:
>
> Functions.compose(#(x){ "a" + x }, #(x){ x + "b"}).apply("x")
>    
The problem is that the type-variable 'B' of Functions.compose is 
inferred to be 'Object' and not 'Integer' as you expect. As such, the 
expression 'x * x' (where x has type Object) is erroneous. On the other 
hand, if you use '+' for appending strings, an Object argument is 
perfectly fine.

Note also that the 'B' type-variable is under-constrained, given that 
the return type of the second lambda expression in the call to 'compose' 
cannot be inferred from the lambda body (as it contains an expression 
like 'x/3' which has no meaning without a proper type for 'x'); 
moreover, since the called method is generic, the target type doesn't 
help much in inferring an useful type for the lambda return type.

Maurizio
> works.
>
> On 25 August 2010 16:25, Thomas Jung<thomas.andreas.jung at googlemail.com>  wrote:
>    
>> I've checked if the current prototype solves the problem and it does not:
>>
>> Function<Integer, Integer>  a = Functions.compose(#(x){ x * x }, #(x){ x / 3 });
>>
>> operator * cannot be applied to Object,Object
>>                 Functions.compose(#(x){ x * x }, #(x){ x / 3 });
>>
>> It works with the explicit type:
>> Function<Integer, Integer>  a = Functions.compose(#(Integer x){ x * x
>> }, #(x){ x / 3 });
>>
>> Thomas
>>
>>
>> On 7 August 2010 19:24, maurizio cimadamore
>> <maurizio.cimadamore at oracle.com>  wrote:
>>      
>>> On 07/08/2010 15:57, Thomas Jung wrote:
>>>        
>>>> Hi Rémi,
>>>>
>>>> you're right. Defining
>>>>
>>>> public static<A,B,C>    Function<A,C>    simpleCompose(Function<B,C>    g,
>>>> Function<A, B>    f){
>>>>      return Functions.compose(g,f);
>>>> }
>>>> Function<String, String>    c = simpleCompose(#(x){ "a" + x }, #(x){ x + "b"
>>>> });
>>>>
>>>> works. Is there is way to get some debugging information of the type
>>>> inferencer?
>>>>
>>>> Thomas
>>>>
>>>>          
>>> Hi
>>> as Remi pointed out in an earlier email, there's a bug when the target
>>> method of a SAM conversion has a wildcard in return type position. Wildcards
>>> in argument types work w/o problems - a fix for this problem will be
>>> available soon.
>>>
>>> Thanks
>>> Maurizio
>>>        
>>>> On 7 August 2010 15:16, Rémi Forax<forax at univ-mlv.fr>    wrote:
>>>>
>>>>          
>>>>>   Le 07/08/2010 09:58, Thomas Jung a écrit :
>>>>>
>>>>>            
>>>>>> Hi,
>>>>>>
>>>>>> I'm playing a bit with the prototype (i.e. I've not read the specs in
>>>>>> full) and I'm puzzled after my second step.
>>>>>>
>>>>>> The initial code that uses Function
>>>>>>
>>>>>> (http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/base/Function.html)
>>>>>> is:
>>>>>>
>>>>>> Function<String, String>      a = #(x){ "a" + x };
>>>>>> Function<String, String>      b = #(x){ x + "b" };
>>>>>> assertEquals("axb", Functions.compose(a, b).apply("x"));
>>>>>>
>>>>>> This works with type inference and does the conversion to the type
>>>>>> Function<F,T>. But if I inline the lambda expression it won't convert
>>>>>> them.
>>>>>>
>>>>>> Function<String, String>      c = Functions.<String, String>
>>>>>> compose(#(String x){ "a" + x }, #(String x){ x + "b" });
>>>>>>
>>>>>> I've added all type annotations to rule out that this is the problem.
>>>>>> The error message is:
>>>>>> "method compose in class Functions cannot be applied to given types".
>>>>>> (Can I get more information here about the types/problem?)
>>>>>>
>>>>>> Is this not supported?
>>>>>>
>>>>>> Thomas
>>>>>>
>>>>>>
>>>>>>              
>>>>> This is a bug, the prototype have a problem to infer types
>>>>> if there is a wilcard in the middle.
>>>>>
>>>>> by example, this doesn't compile:
>>>>> Function<String, ? extends String>    b = #(x){ x + "b" };
>>>>>
>>>>> So you can't use compose which is declared:|*
>>>>> *|<A,B,C>
>>>>>
>>>>> <../../../../com/google/common/base/Functions.html#compose%28com.google.common.base.Function,%20com.google.common.base.Function%29>Function
>>>>> <../../../../com/google/common/base/Function.html><A,C>    |compose
>>>>>
>>>>> <../../../../com/google/common/base/Functions.html#compose%28com.google.common.base.Function,%20com.google.common.base.Function%29>(Function
>>>>> <../../../../com/google/common/base/Function.html><B,C>    g, Function
>>>>> <../../../../com/google/common/base/Function.html><A,*? extends* B>    f)|
>>>>>
>>>>> Rémi
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>            
>>>>
>>>>          
>>>
>>>        
>>      



More information about the lambda-dev mailing list