Call for Dicussion: JEP: Java Expression Trees API

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed May 8 12:18:57 UTC 2024


On 06/05/2024 18:50, Paul Sandoz wrote:

>> Just wanted to mention that there might be alternative implementations addressing this requirement.
>> 1. Structural quoting (a la C#) - derives from the variable type, e.g. Quoted<T>. So, the user understands that the lambda body will be accessible.
> There are some challenges with Java’s type system, which is why we embedded up where we are with the current approaches. Maurizio is better able than I to describe these challenges.

Hi,
we have explored approaches such as |Quoted<T>| (where |T| is a 
functional interface) early on. And found them a bad fit for Java. The 
main issue we faced is that being a functional interface, as per today’s 
JLS, is a predicate on class declarations not types (there was some 
intense discussion on this point during Java 8). But here we have 
something that can be treated as a functional interface or not, 
precisely depending on its type (e.g. the type parameter). E.g. a 
|Quotable<T>| is a functional interface or not depending on |T|. This is 
a pretty deep big departure from how the spec currently deal with 
functional interfaces.

One possibility would be for the compiler/spec to ignore the 
|Quoted<T>|, and just focus on the inner |T|, and then add the quoting 
back, after type-checking. But doing so leads to (bad) edge cases. For 
instance, Java 8 supports a form of inference of the target type from 
the explicit lambda parameter types, in this case:

|Function<?, ?> f = (Integer i) -> ""; |

In this case, the type of the lambda expression is not just |Function<?, 
?>| (the target type), but |Function<Integer,Object>|. That is, the 
compiler tries to get rid of the wildcards before attempting to 
type-check the lambda expression (this step is performed to avoid 
wildcards popping up when checking the lambda body). But with quoting, 
this won’t compose well - e.g.:

|Quoted<Function<?, ?>> f = (Integer i) -> ""; |

Will give an error:

|error: incompatible types: Quoted<Function<Integer, Object>> cannot be 
converted to Quoted<Function<?, ?>> Quoted<Function<?, ?>> f = (Integer 
i) -> “”; ^ |

That is, the functional interface type inferred by the compiler (by 
dropping wildcards) is now incompatible with the target type (because of 
the way in which generics type-argument containment rules work). To make 
things work, the client would need at least to do this:

|Quoted<? extends Function<?, ?>> f = (Integer i) -> “”; |

Overall it felt like we were pushing against the physics of the language 
here. Serializable lambdas (with all their limitations) were a strong 
precedent to build on top of, which didn’t suffer from any of the 
limitations described above.

Maurizio​

​
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/babylon-dev/attachments/20240508/6da5b1ba/attachment.htm>


More information about the babylon-dev mailing list