Am 12.01.2018 um 15:00 schrieb Daniel Sun:
Hi Jochen,
but I think you should then not use the closure inner class mechanism.
I remain the implementation for non-native lambda[1] to make lambda work in
legacy code, where closures are widely used. For example, `[1, 2,
3].collect(e -> e + 1)`
ok, then forget about my other mail from a minute ago ;)
We have to be a bit careful here imho. Defining an inner class, means
additional class loading times, accessing private fields becomes also
more tricky. If you want to be able to be "equal" to the javac code as
much as possible, then you should not base this on closure so much. In
fact I think our closures should be based on lambdas instead. If we
already had solved all the lambda problems, then I would change Closure
accordingly actually. Yes, for a first step basing them on Closure is
nice, but that can easily backfire.
For example
class SomeClass {
private foo;
def m(bar) {
SomeFunctionalInterface x =
(it -> println "I am a lambda: $foo and $bar")
return x
}
}
Following the Closure route of dynamic Groovy means here the following:
(1) I create a Closure for the lambda as inner class, one such class per
lambda
(2) I will ignore the overhead of the Closure instance generation
(3) I use the asType mechanism to create a dynamic proxy for my Closure
(4) If somebody creates a sublcass of Someclass accessing the private
field foo gets complicated
(5) actually using the lambda would go through doCall/call
(6) accessing bar is realized through
and for the static case
* 1-3 and 5 will still apply. For point (4) there will be a bridging
method (synthetic public static) in SomeClass, which is directly called
to access the field. the static compiler is adding this method on its
own (very very very late)
What I wish for in a static compile lambda is the following:
* bar is a parameter to the method generated for the lambda
* there is no groovy dynamic call involved to get to the lambda code
* the proxy for SomeFunctionalInterface is generated by the lambda factory
* foo is accessed directly through get field
And what I would wish for for the future Closure is. There is no inner
class Closure anymore, instead Closure is just a holder for symbolic
references and maybe some instances. Bar for example would still come in
through the constructor. The Closure instance itself would be a
parameter to the lambda method implementation (together with owner and
such). And finally: there is a way to define a stateless Closure (but
maybe the lambdas are the way for this)
I thought you need that only to enable reflection to find your inner
classes.
Could you make it a bit detail? To be honest, I can not get your words...
If you use reflection on a class you can ask this class what inner
classes it has. For this there is in bytecode an entry in the inner
class table. The inner class has an outer class attribute which can be
used by Reflection to query for the enclosing class (similar for
enclosing method). For the JVM itself I think those all are not
required. The JVM does not care if a class is Bar or Foo$Bar and if the
constructor takes an instance of Foo or not unlesss you call that
constructor. The JVM even requires those bridge methods to access the
private fields of the enclosing class. Which is also the reason why
Groovy had this information wrong for a long time and not very many did
really care.
bye Jochen