groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: About the native-lambda branch
Date Fri, 12 Jan 2018 18:15:32 GMT


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


Mime
View raw message