Problem with method references
Tomasz Kowalczewski
tomasz.kowalczewski at gmail.com
Tue Jan 4 10:01:49 PST 2011
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