+1 On Mon, May 2, 2016 at 4:44 PM, Cédric Champeau <cedric.champ...@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>