<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">The design center for lambdas and
      method reference is that the key concept is _functional
      interfaces_, which can be thought of as nominal function types.  <br>
      <br>
      Both lambdas and method references are expressions that evaluate
      to instances of functional interfaces.  When you have a method
      m(Supplier<Foo> s), you can create s with a lambda, a method
      or constructor references, with an anonymous subclass of Supplier,
      with an instance of a named subclass of Supplier, etc.  Once you
      have a Supplier, how it came into being is irrelevant.<br>
      <br>
      Saying that conversion from method references to functional
      interface instances carries extra metadata (e.g., some extra
      interface like IAmAMethodRef, from which you could get the
      symbolic information about what method it refers to), is a viable
      feature idea.  However, a method like m(Supplier<Foo> s)
      that really wants a method ref, has no way to express this in the
      method signature.  This means that if I pass it `m(() -> new
      Foo(7))`, when `m` tries to cast its supplier to IAmAMethodRef, it
      would get a CCE or similar.  THis is what I mean by a dynamic
      failure -- you wrote a program which conforms to the static type
      system, but you still managed to pass "bad data" to a method.  <br>
      <br>
      Now, maybe you want more, not only for method refs to be
      scrutable, but to add some new types, like
      ConstructorRef<T>.  Then we could claw back static type
      safety, at the cost of more complexity, and potential ambiguity
      (What if there is an overload between m(Supplier<T>) and
      m(ConstructorRef<T>, should the language try to resolve
      that?)<br>
      <br>
      All of this is to say, this is a viable part of the design space,
      but the incremental expressiveness is lower than you might think,
      and the incremental cost and complexity is higher than you might
      think.<br>
    </font><br>
    <br>
    <div class="moz-cite-prefix">On 12/9/2024 12:30 PM, Peter Eastham
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAN+txM9jMTPuZUH7OnEPKG5yi921mPpSv+nF2bAxch7RUqtFRw@mail.gmail.com">
      
      <div dir="ltr">Hey Brian,<br>
        <br>
        I'm hesitant to respond further, as I'd like some time to do a
        proper write up that can provide a more solid context for
        discussion than my simple example provided. <br>
        <br>
        You are right in that "createQuery(Customer::new)" would be
        behaving around the Constructor, instead of utilizing it as a
        "Supplier<Customer>". The exact type this would use is not
        something I have fully considered, and I agree that the current
        Functional Interfaces aren't sharp enough to restrict it to only
        Method References. It's also not a solution to have Method
        References resolve to their own type without being able to still
        work in those situations. <br>
        <br>
        When you say Dynamic Failure, can you explain that a bit more?
        My assumption is that there it would be an issue if you
        dynamically transform the class, specifically the method in the
        reference. However I'm unsure if that is any different of a
        failure than if you did the same with the current use case.<br>
        <br>
        Thanks,<br>
        -Peter</div>
      <br>
      <div class="gmail_quote gmail_quote_container">
        <div dir="ltr" class="gmail_attr">On Mon, Dec 9, 2024 at 8:56 AM
          Brian Goetz <<a href="mailto:brian.goetz@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">brian.goetz@oracle.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div> <font size="4" face="monospace">By "greater access", I
              think you mean "if they could be reflected on as a
              function, not just a thunk of behavior", yes?  Then
              `createQuery(Customer::new)` would be able to reflect over
              the constructor reference and see "oh, it's a constructor
              for Customer".  <br>
              <br>
              We've given a good deal of thought to this problem, but
              it's messy for a number of reasons, including erasure and
              limitations on the static type system.  Does createQuery
              mean to limit to method references, rather than all
              lambdas?  If so, then Supplier<T> is not a sharp
              enough type, and users could pass a Supplier that ends up
              causing a dynamic failure.  If not, then it sounds like
              what you want is to reflect over the concrete shape of the
              supplier, which runs into erasure problems (among others
              -- what if you intended a Supplier<Foo>, but the
              lambda you passed instantiates a
              Supplier<SubtypeOfFoo> where the subtype is
              inaccessible to the framework.)  <br>
              <br>
              So while it is possible to associate more metadata with
              method references than we currently do, and we've
              considered it, most of the obvious paths run into obvious
              roadblocks just a bit farther down the road.  <br>
              <br>
              <br>
            </font><br>
            <br>
            <div>On 12/8/2024 8:52 PM, Peter Eastham wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">Hi Amber team,<br>
                <br>
                Earlier this week I was playing around with fluent API
                design, and I believe Java could benefit from some
                improvements to the usage of Method References, I'll
                keep this short with the following example.<br>
                <br>
                Lets take the following JPA Criteria from section 6.3.3
                of the Specification, (Only for an example of what an
                API could begin doing, not should do)<br>
                CriteriaQuery q = cb.createQuery(Customer.class); <br>
                Root customer = q.from(Customer.class);<br>
                Join order = customer.join(Customer_.orders,
                JoinType.LEFT);<br>
                q.where(cb.equal(customer.get(Customer_.status),
                1)).select(customer);  <br>
                <br>
                If there was greater access to the Method Reference more
                implicit information could be passed, reducing the
                noise,<br>
                CriteriaQuery q =
                CriteriaQuery.createQuery(Customer::new)<br>
                  .leftJoin(Customer::orders)<br>
                  .where(Object::equals, Customer::status, 1);<br>
                var result = q.select();<br>
                <br>
                Regarding what should be available, the resolved Class
                and Method name at least, anything else I'd leave up to
                the feasibility of the change.<br>
                <br>
                Thanks,<br>
                -Peter</div>
            </blockquote>
            <br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>