<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Oct 5, 2018, at 4:18 PM, Brian Goetz <<a href="mailto:brian.goetz@oracle.com" class="">brian.goetz@oracle.com</a>> wrote:</div></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class=""><blockquote type="cite" cite="mid:CAGKkBksaw_3k7V-SjXqVCDFvp_82mHtX5gmRUpx40QFA+XCioQ@mail.gmail.com" class=""><div dir="ltr" class=""><div class="gmail_quote">
          <div class="">Can the expression before the :: refer to any method
            parameters? Of course, it would still expect to pass those
            parameters into the method, so it's <i class="">weird</i> to have
            the same parameter used in both ways, but does it make sense
            to forbid it?</div>
          <br class="">
        </div>
      </div>
    </blockquote>
    <br class="">
    Yes, it makes sense to forbid.  Here's why.  <br class="">
    <br class="">
    The framing of<br class="">
    <br class="">
        method declaration = behavior literal<br class="">
    <br class="">
    is meant to suggest that the thing on the RHS can be computed ONCE,
    and that's the "body" of the method.  Therefore, it should only be
    computable based on what is known in the context of the method
    (static state for static methods, instance state for instance
    method.)  It is not merely a shorthand for "take the method ref,
    turn it into a lambda, and then turn the body of that lambda into a
    method body."  <br class="">
    <br class="">
    So the thing on the left of the :: must be something that could be,
    say, the RHS of a field initializer of the appropriate static-ness. 
    <br class="">
    <br class="">
    <blockquote type="cite" class="">Now we want to introduce a second way to use
      method references, where that creation/evaluation distinction
      doesn't exist. </blockquote>
    <br class="">
    Same distinction.  You can think of the creation as happening in
    <init> / <clinit>.  <br class="">
    <br class="">
    Now, a fair question is: when should we evaluate that LHS?  And, is
    it an error or warning if that LHS is, for example, a nonfinal
    field?  Good question!  Thanks for bringing this up.  <br class=""></div></div></blockquote><div><br class=""></div></div>Yes, glad to see more discussion about this. We talked about it a bit weeks ago, but never got past the "yeah, that's something to think about" stage.<div class=""><br class=""></div><div class="">The challenge seems to be finding the right intuition.</div><div class=""><br class=""></div><div class="">1) One interpretation is that the method reference must be a constant—something that can be translated into a JVM linkage instruction without executing any code. (Meanwhile, on the JVM side we've explored some features for declaring concrete methods without a Code attribute.)</div><div class=""><br class=""></div><div class="">2) Another interpretation is Brian's here: the evaluation of a method ref's receiver parameter occurs at class initialization, as if there were an initialization of a static field. This suggests that "linkage" of the method (i.e., computation of a function-like entity representing the body) occurs at class initialization.</div><div class=""><br class=""></div><div class="">3) Or, also suggested above: the evaluation occurs in a constructor, again as if a (in this case, instance) field were initialized with the expression.</div><div class=""><br class=""></div><div class="">4) The evaluation occurs after the constructor has completed, making all fields—including those initialized in the constructor—available.</div><div class=""><br class=""></div><div class="">5) The evaluation occurs just before first method invocation.</div><div class=""><br class=""></div><div class="">6) There is no "linkage" step, the method reference is re-computed on every invocation. Method parameters are in scope. This is the "syntactic sugar" approach, and the one Kevin is taking issue with.</div><div class=""><br class=""></div><div class="">I don't know the right answer, but here are some considerations:</div><div class=""><br class=""></div><div class="">- Another problem with referring to method parameters is that users might expect to exclude a referenced parameter from the parameters passed to the method ref, but the behavior ends up being really ad hoc:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">       </span>static void m1(Foo x, Bar y) = x::m; // invoke x.m(x,y) or x.m(y)?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">   </span>static void m2(Foo x, Bar y) = y::m; // invoke y.m(x,y) or y.m(x)?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>static void m3(Foo x, Bar y) = f(x,y)::m; // invoke obj.m(x,y) or obj.m()?</div><div class=""><br class=""></div><div class="">- It's not totally clear what we do with 'this'. Kind of seems like it should be treated as the first parameter to be passed, but there are also examples in the JEP that ignore it. And is it allowed to be referenced by the receiver expression?</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">     </span>void reverse() = Collections::reverse; // invoke Collections.reverse(this)?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">       </span>int length(String s) = String::length; // invoke s.length()?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">      </span>void altMethod() = ThisClass::method; // invoke this.method()?</div><div class=""><span class="Apple-tab-span" style="white-space:pre">    </span>void altMethod2() = this::method; // legal?</div><div class=""><br class=""></div><div class="">- Delegation typically depends on an instance field provided as a constructor parameter, which won't work with (1)-(3), and if the delegation target is meant to be mutable, won't work with (4)-(5) either.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">   </span>Foo target;</div><div class="">        int m1() = target::m1;</div><div class=""><span class="Apple-tab-span" style="white-space:pre">   </span>int m2() = target::m2;</div><div class=""><br class=""></div><div class="">- Ideally, we would not like to further complicate the class/instance initialization story by adding new execution timing, as in (4) or (5). What Brian's story ((2) and (3)) has going for it is that we already have the infrastructure to describe the timing of these evaluations.</div><div class=""><br class=""></div><div class="">- We can simplify things considerably by prohibiting the expression form—must use Type::name. Effectively, (1) but without support for constant expressions. That means giving up on some use cases.</div><div class=""><br class=""></div></body></html>