Problem with method references

Brian Goetz brian.goetz at oracle.com
Tue Jan 4 10:08:32 PST 2011


this#getArgCount should result in a bound instance method reference, with 'this' as the receiver.  Most likely the shorthand #getArgCount will correspond to this#getArgCount.

On Jan 4, 2011, at 10:01 AM, Tomasz Kowalczewski wrote:

> Maurizio,
> 
> I didn't suggest any semantic changes, just described what is my gut
> feeling about what 'this#getArgCount' should mean. Nevertheless thanks
> for looking into it. I appreciate hard work of all you guys working on
> the lambda implementation.
> 
> On Tue, Jan 4, 2011 at 5:02 PM, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>> On 04/01/11 14:46, Tomasz Kowalczewski wrote:
>>> 
>>> Thanks for your explanation Maurizio, this is very interesting.
>>> 
>>> The Extractor interface is included in my original email (however, you
>>> were right about how it looks). I understand that this#getArgCount
>>> will be translated to a SAM with method that forwards the call to
>>> 'this' (so no explicit argument of type LambdaInConstructorExample is
>>> required). But in the constructor I am not using 'this#getArgCount', I
>>> am using LambdaInConstructorExample#getArgCount. That why, at least
>>> for me, this situation is very unintuitive.
>>> When working from a non-static context, is there a possibility to SAM
>>> convert getArgCount to the Extractor interface?
>> 
>> I understand your point - however, I think that, if we changed the semantics
>> of this#getArgCount as you describe, another unintuitive example would
>> pop-up:
>> 
>> interface Extractor {
>> int getX();
>> }
>> 
>> class Test {
>>   int getArgCount() { ... }
>> 
>>   Exctractor e = this#getArgCount;
>> }
>> 
>> Unless we let the compiler perform the automatic expansion only if the
>> parenthesis are omitted from the method references - which would lead to
>> this#getArgCount() being semantically different w.r.t. this#getArgCount
>> 
>> Maurizio
>> 
>>> On Tue, Jan 4, 2011 at 3:19 PM, Maurizio Cimadamore
>>> <maurizio.cimadamore at oracle.com>  wrote:
>>>> 
>>>> On 03/01/11 10:10, Tomasz Kowalczewski wrote:
>>>>> 
>>>>> package org.tkowalcz.lambda.extractor;
>>>>> 
>>>>> public class LambdaInConstructorExample {
>>>>> 
>>>>>   public static void main( final String[] args ) {
>>>>>     // Compiles fine
>>>>>     Extractor x = LambdaInConstructorExample#getArgCount;
>>>>>   }
>>>>> 
>>>>>   public LambdaInConstructorExample() {
>>>>>     // Error
>>>>>     Extractor x = LambdaInConstructorExample#getArgCount;
>>>>>   }
>>>>> 
>>>>>   public int getArgCount() {
>>>>>     return 1;
>>>>>   }
>>>>> }
>>>> 
>>>> There is no bug here. The first method reference compiles because a
>>>> non-static method is being referenced from a static context - in such
>>>> cases,
>>>> the following expansion is automagically applied by the compiler:
>>>> 
>>>> If f is an instance method of Z whose signature is A,B->C, then #obj.f is
>>>> of
>>>> type A,B->C and #Z.f is of type Z,A,B->C.
>>>> 
>>>> Which means that, in the first case, the compiler is looking for a
>>>> signature
>>>> of the kind (LambdaInConstructorExample)->int.
>>>> 
>>>> Since the second method reference occurs in a non-static context, no
>>>> automatic expansion is applied, which means the compiler will look for a
>>>> signature of the kind ()->int.
>>>> 
>>>> Now, depending on how you declare the target method in the SAM type
>>>> Extractor, you will not be able to get both method references to compile,
>>>> as
>>>> the compiler will be looking for different signatures. I guess that,
>>>> looking
>>>> at your output, your SAM type declaration looks like the following:
>>>> 
>>>> interface Extractor {
>>>> int getX(LambdaInConstructorExample arg);
>>>> }
>>>> 
>>>> Maurizio
>>>> 
>>>> 
>> 
>> 
> 
> -- 
> Tomasz Kowalczewski
> 



More information about the lambda-dev mailing list