groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <>
Subject Re: [VOTE] Release Apache Groovy 2.6.0-alpha-1
Date Tue, 22 Aug 2017 21:12:59 GMT
On 22.08.2017 14:11, Jesper Steen Møller wrote:
> It's two problems in one.
> A) The code generation itself is not quite so bad as you might think, 
> especially if we for a moment ignore serializable lambdas. For instance, 
> here's how Eclipse's JDT does it:
> It's a matter of recording a bootstrap method in the constant pool of 
> the class, and then emitting a invokeDynamic to "hit" that bootstrap method.
> B) The really tricky issue is the type analysis you need to have in 
> place to figure out the type signature of the Lambdas type signature and 
> implementation method. Both javac and  ECJ grew significantly in 
> complexity in working to find this out, including backtracking. The 
> choice of the lambda's type will in turn affect which possible overload 
> to call.
> Only the static compilation will have a chance to do this right, and 
> getting it "perfect" (including variable and member capture) is pretty 
> tricky.

This can shed some light on the comments above:

>     A lambda expression (§15.27) is potentially compatible with a functional interface
type (§9.8) if all of the following are true:
>       *  The arity of the target type's function type is the same as the arity of the
lambda expression.
>       *  If the target type's function type has a void return, then the lambda body is
either a statement expression (§14.8) or a void-compatible block (§15.27.2).
>       *  If the target type's function type has a (non-void) return type, then the lambda
body is either an expression or a value-compatible block (§15.27.2).

We would have no problem with the arity if we stay with the lambda 
syntax. A Closure expression would already have problems here. But 
without looking at the code in more detail you cannot say if the lambda 
is actually returning something. and if you have 
->System.out.println(1); You need to know if println is void or not to 
be sure if the lambda returns something or not. That alone already 
implies a lot of compiler work we do only in the static compiler right 
now. But that is not enough:

> void f(Function<String, Integer> x) {}
> void f(IntFunction<String> x) {}
> f(x -> x.hashCode());

which one is to be taken here? For the IntFunction version we actually 
would have a resulting signature for the lambda of (String)int, for the 
Function (String)Integer. I think the java compiler will fail to compile 
this. But what could a dynamic Groovy do here?

As for static compilation... I think what we could implement which is 
not too complicated is to actually first determine the arity to get 
potentially fitting signatures and ignoring the return type, then apply 
the signature to the types of the lambda and see if that will compile 
and what the return type will be. If that would compile and the return 
type fits, we have a match. Then we would proceed with the next 
signature. It is ambiguous if there is more than one match.

I think with this simple approach we should cover all problems I know in 
combination with lambdas. And of course the case above would then not 
compile because int and Integer are both valid return types. Would be 
nice if somebody could show me a counter example

bye Jochen

View raw message