<!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>