groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Guillaume Laforge <glafo...@gmail.com>
Subject Re: Automatic closure coercion and delegate
Date Mon, 02 May 2016 14:56:54 GMT
+1

On Mon, May 2, 2016 at 4:44 PM, C├ędric Champeau <cedric.champeau@gmail.com>
wrote:

> Hi guys,
>
> I've been grumpy about this for a bit too long to keep it for myself, so
> let me explain the issue :)
>
> Imagine you have a Java method that accepts a SAM type:
>
> interface Action<T> {
>    void execute(T object)
> }
>
> class Person {
>     String name
> }
>
> void configure(Action<Person> config) {
>    config.execute(person)
> }
>
> then, you can call it in Groovy like this:
>
> configure {
>    it.name = 'Bob'
> }
>
> Whereas if we had a closure version, a nice and idiomatic way would be to
> write:
>
> configure {
>    name = 'Bob'
> }
>
> Note that in the `Action` version, we have to prefix everything with "it.".
>
> My wish is to make automatic closure coercion automatically set the
> delegate to the first argument, if available, and the delegation strategy
> to delegate first.
>
> Basically, it is important to integrate with Java 8 style SAM types and
> still benefit from a nicer Groovy DSL _without_ having to change the source
> files. Typically, we don't have access to the JDK sources, so we have to
> write:
>
> def max =['Cedric','Jochen','Guillaume', 'Paul'].stream()
>   .mapToInt { it.length() }
>   .max()
>   .orElse(0)
>
> Where with this strategy we could use:
>
> def max =['Cedric','Jochen','Guillaume', 'Paul'].stream()
>   .mapToInt { length() }
>   .max()
>   .orElse(0)
>
> Of course, it may look a bit superficial but it is super important for
> nice DSLs like in Gradle. Typically, Gradle has a lot of domain objects
> that use the `Action<T>` interface above. Those actions allow the user to
> configure the domain objects typically from plugins written in Java (where
> you cannot use a closure). Since the `Closure` equivalent methods are
> always the same and that it's super simple to forget to implement one,
> Gradle chose to _not_ implement the `Closure` versions. Instead, they are
> generated at runtime, so the objects are decorated with one `Closure`
> method for each `Action` one.
>
> Unfortunately, this approach is defeated as soon as you want to use static
> compilation: then, you have no choice but implementing the `Closure`
> versions. This might be an option for Gradle (even though it would be very
> tedious), but not for all cases (we could also do this using extension
> methods, though, but really, you'd be doing this for _all_ domain objects).
> I think I could write a code generator that takes all java classes and
> generates an extension class with closure versions for all, also, but I'd
> like to know first what you think of this idea...
>
>


-- 
Guillaume Laforge
Apache Groovy committer & PMC Vice-President
Product Ninja & Advocate at Restlet <http://restlet.com>

Blog: http://glaforge.appspot.com/
Social: @glaforge <http://twitter.com/glaforge> / Google+
<https://plus.google.com/u/0/114130972232398734985/posts>

Mime
View raw message