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