You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Daniel Sun <re...@hotmail.com> on 2017/02/07 16:20:11 UTC

[VOTE]About the implementation of lambda expression

Hi all,

      Jesper and I discussed the *real* lambda expression(i.e. Java8's
lambda expression) just now. As Jesper found, Java8's lambda expression is
implemented in Java as an invokedynamic call which makes use of a bootstrap
method calling into a class called the LambdaMetafactory
(https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html).
and puts the body of the lambda expression into a hidden method on the
class. The LambdaMetafactory sets up the magic class which holds any escaped
variables and implements the functional interface. To work, it requires
EXACT type information,* so it's only possible to do this in static
compilation*.

      Current lambda expression is based on closure, so it can work well in
the default mode and static compilation mode. But if we want the *real*
lambda expression, it will be only available in the static compilation
mode(as above said). When developers does not enable static compilation, we
provide them lambda expression based on closure or provide no lambda
expression at all? I prefer the universal version of lambda expression, i.e.
lambda expression based on closure with some warning(such as changing the
delegation strategy of 'this' is forbidden, reference:
http://groovy-lang.org/closures.html#_delegation_strategy)

- [ ] A, lambda expression based on closure with warning(or error prompt)
- [ ] B, *real* lambda expression is available *in the static compilation
mode* while lambda expression based on closure is available *in the default
mode*
- [ ] C, *real* lambda expression is only available *in the static
compilation mode* while *no lambda expression* is available *in the default
mode*

P.S. My vote is A

Cheers,
Daniel.Sun



--
View this message in context: http://groovy.329449.n5.nabble.com/VOTE-About-the-implementation-of-lambda-expression-tp5738486.html
Sent from the Groovy Dev mailing list archive at Nabble.com.

Re: [VOTE]About the implementation of lambda expression

Posted by Daniel Sun <re...@hotmail.com>.
Hi Rémi,

      Thanks for your explaination and suggestion. 
      The following email was sent by Jochen in another thread. The
implementation of lambda expression can be discussed here together :)

Cheers,
Daniel.Sun
----------------------------------------- Jochen's email
--------------------------------------
On 07.02.2017 17:39, Daniel Sun wrote: 
[...] 
> 
>   * We have a basic choice: 1) Use Java-lambda semantics or 2) 
>     Groovy-closure semantics. As a variation on 2, we can add some help 
>     for people pasting Java code into a Groovy program. 
> 
> 
> Agreed. 

hmm... let me add some thoughts to this... 

I see a lambda as a kind of lightweight proxy, that provides an 
implementation for a series of functional interfaces. In that matter 
they are like "closure as SomeFunctionalInterface", only that our 
solution is not lightweight. 

Since we know the internals we can ignore the proxy facade and directly 
use the method that realizes the proxy. All that is then required is to 
transform call arguments to the types the implementing method needs. 

It would be very possible to use the LambdaMetaFactory for for example 
"closure as SomeFunctionalInterface". 

At the same time we can provide our own LambdaMetaFactory (ignoring 
Java9 problems). The "problem" is the identity of the implementing 
method and what signature you use for it. In dynamic Groovy you can go 
with object for most parts and have no trouble. 

What we are really missing is the ability to decide at compile time 
between two overloaded methods each taking functional interfaces. Only 
this requires extended static analysis. If we delay that part to 
runtime, like we do today for SAM Closures, then we do not need this as 
long as the interfaces differ on a level recognizable after type erasure. 

if we have for example one method taking List  and another taking 
List as parameter type for the method of the functional interface, 
then we really really need a static analysis. 

In the end that boils for me down to: 
* dynamic Groovy can most probably not use LambdaMetaFactory and could 
probably use the already existing ifrastructure the invokedynamic port 
provides. 
* static Groovy can use LambdaMetaFactory but needs to be improved on 
the compiler level 

bye Jochen 




--
View this message in context: http://groovy.329449.n5.nabble.com/VOTE-About-the-implementation-of-lambda-expression-tp5738486p5738513.html
Sent from the Groovy Dev mailing list archive at Nabble.com.

Re: [VOTE]About the implementation of lambda expression

Posted by Remi Forax <fo...@univ-mlv.fr>.
Hi Daniel,

On February 7, 2017 5:20:11 PM GMT+01:00, Daniel Sun <re...@hotmail.com> wrote:
>Hi all,
>
>      Jesper and I discussed the *real* lambda expression(i.e. Java8's
>lambda expression) just now. As Jesper found, Java8's lambda expression
>is
>implemented in Java as an invokedynamic call which makes use of a
>bootstrap
>method calling into a class called the LambdaMetafactory
>(https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html).
>and puts the body of the lambda expression into a hidden method on the
>class. The LambdaMetafactory sets up the magic class which holds any
>escaped
>variables and implements the functional interface. To work, it requires
>EXACT type information,* so it's only possible to do this in static
>compilation*.

It's not fully true.
javac generate a lambda body with the exact type info so the lambda proxy class has to be created with the exact info, if the groovy compiler desugar a lambda body using Objects, the lambda factory will only need Objects. 
Also, the groovy compiler do not have to call the bootstrap method of the lambda meta factory directly so the runtime can also find the target dynamically if that info is available and ask the user to insert a cast to the interface otherwise.
You can also imagine that the groovy runtime can use the interfaces of java.util.function if no interface is provided an do a lambda to lambda conversion at runtime if the number of parameters match but not the interface.



>
>  Current lambda expression is based on closure, so it can work well in
>the default mode and static compilation mode. But if we want the *real*
>lambda expression, it will be only available in the static compilation
>mode(as above said). When developers does not enable static
>compilation, we
>provide them lambda expression based on closure or provide no lambda
>expression at all? I prefer the universal version of lambda expression,
>i.e.
>lambda expression based on closure with some warning(such as changing
>the
>delegation strategy of 'this' is forbidden, reference:
>http://groovy-lang.org/closures.html#_delegation_strategy)
>
>- [ ] A, lambda expression based on closure with warning(or error
>prompt)
>- [ ] B, *real* lambda expression is available *in the static
>compilation
>mode* while lambda expression based on closure is available *in the
>default
>mode*
>- [ ] C, *real* lambda expression is only available *in the static
>compilation mode* while *no lambda expression* is available *in the
>default
>mode*
>
>P.S. My vote is A

Java lambdas are identity less so there is more than just how this/super behave, as an example, an array of lambdas can be differently than an array of reference. 

And also please do not forget that the code of the meta factory can change for any updates of the JDK.

>
>Cheers,
>Daniel.Sun

Rémi 

>
>
>
>--
>View this message in context:
>http://groovy.329449.n5.nabble.com/VOTE-About-the-implementation-of-lambda-expression-tp5738486.html
>Sent from the Groovy Dev mailing list archive at Nabble.com.

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.