Problem with method references

Peter Levart peter.levart at marand.si
Thu Jan 13 23:53:10 PST 2011


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.

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