On Mon, May 2, 2016 at 5:25 PM, Joe Wolf <joew...@gmail.com> wrote: > [...] > > [Hi, all. This is my first post to the list--been a happy Groovy user > since version 1.5] >
Welcome here and thanks for using Groovy since 1.5!!! :-) Guillaume > > -Joe > > > On Mon, May 2, 2016 at 10:56 AM, Guillaume Laforge <glafo...@gmail.com> > wrote: > >> +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> >> > > -- 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>