Problem with method references
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jan 14 01:24:38 PST 2011
On 14/01/11 07:53, Peter Levart wrote:
> On 01/04/11, Maurizio Cimadamore 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
>>
> Hello Maurizio,
>
> I see that referencing instance methods from static context is a desirable feature, but syntax-wise I aggree with Neal that the same expression should not change its meaning if moved from static to instance context or vice-versa (when both contexts are legal). So I propose that the syntax:
>
> #methodName
>
> be made illegal for referencing instance methods from static context.
I agree - since #methodName is essentially a shortcut for
this#methodName, it is sensible to reject it in a static context.
Thanks for the example - I will make sure to add it to our regression
tests as soon as I add support for #this.
Maurizio
> for example (using infix '#' - equivalent is possible with prefix '#'):
>
> class C {
>
> public int m(String s) { ... }
>
> public static int sm(String s) { ... }
>
> C() {
> StringToInt f1 = this#m;
> StringToInt f2 = #m; // equivalent as above
> CStringToInt f3 = C#m;
>
> StringToInt f4 = C#sm;
> StringToInt f5 = #sm; // equivalent as above
> StringToInt f6 = this#sm; // equivalent as above (to be consistent with method invocation)
>
> new Runnable() {
> public void run() {
> StringToInt f1 = C.this#m;
> CStringToInt f2 = C#m;
> }
> }.run();
> }
>
> static {
> C c = new C();
>
> StringToInt f1 = c#m;
> // #m - illegal
> CStringToInt f2 = C#m;
>
> StringToInt f3 = C#sm;
> StringToInt f4 = #sm; // equivalent as above
> StringToInt f5 = c#sm; // equivalent as above (to be consistent with method invocation)
> }
>
> interface StringToInt {
> int apply(String s);
> }
>
> interface CStringToInt {
> int apply(C c, String s);
> }
> }
>
>
> Regards, Peter
More information about the lambda-dev
mailing list