Groovy in 2014 and beyond -- Groovy Grails eXchange 2014
As usual, Guillaume Laforge will go through the latest developments of the Groovy programming language and will update you with what's going on, what's to come, and beyond the language itself.
• similar to Java 8 interface default methods • Elegant way to compose behavior • multiple inheritance without the « diamond » problem • Traits can also be stateful • traits can have properties like normal classes • Compatible with static typing and static compilation • class methods from traits also visible from Java classes • Also possible to implement traits at runtime 8
String fly() { "I'm flying!" } } class Bird implements FlyingAbility {} def b = new Bird() assert b.fly() == "I'm flying!" « trait », a new keyword for a new concept
String fly() { "I'm flying!" } } class Bird implements FlyingAbility {} def b = new Bird() assert b.fly() == "I'm flying!" a class « implements » a trait
String fly() { "I'm flying!" } } class Bird implements FlyingAbility {} def b = new Bird() assert b.fly() == "I'm flying!" the fly() method from the trait is available
String surf() { 'kite' } } trait WebSurfer { String surf() { 'web' } } class Person { String name } class Hipster extends Person implements KiteSurfer, WebSurfer {} def h = new Hipster() assert h.surf() == 'web' extending a class and implementing the two traits
String surf() { 'kite' } } trait WebSurfer { String surf() { 'web' } } class Person { String name } class Hipster extends Person implements WebSurfer, KiteSurfer { String surf() { KiteSurfer.super.surf() } } def h = new Hipster() assert h.surf() == 'kite' Your class method takes precedence over the traits
String name } class Animal {} class NamedAnimal implements Named {} def na = new NamedAnimal(name: 'Felix') assert na.name == 'Felix' Somewhat artificial to have to create an intermediary class to get named animals
String name } class Animal {} def na = new Animal() as Named na.name = 'Felix' assert na.name == 'Felix' Runtime trait, with Groovy’s usual coercion mechanism
def fact(BigInteger n, accu = 1G) { if (n < 2) accu else fact(n -‐ 1, n * accu) } assert fact(1000) > 10e2566 Downside of tail recursion is you might have to rewrite your algo to be tailrec friendly
@Builder class Person { String firstName String lastName int age } def person = Person.builder() .firstName("Robert") .lastName("Lewandowski") .age(21) .build()
@Builder class Person { String firstName String lastName int age } def person = Person.builder() .firstName("Robert") .lastName("Lewandowski") .age(21) .build() Different implementation strategies available
@Builder class Person { String firstName String lastName int age } def person = Person.builder() .firstName("Robert") .lastName("Lewandowski") .age(21) .build()
{ int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript assert meaningOfLife == 42 You can add your own base methods and properties to all compiled scripts
{ int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript assert meaningOfLife == 42 Define the base script class for this script
{ int meaningOfLife = 42 } @BaseScript(CustomBase) import groovy.transform.BaseScript assert meaningOfLife == 42 Ability to put the annotation on imports & package
methods on File retrofitted on Path as well 25 path.withReader { Reader r -‐> ... } path.eachLine { String line -‐> ... } path.eachFileRecurse { Path p -‐> ... } path << 'some content' path << bytes path.readLines() … Feature request to add all the java.nio.file.Files static utility methods as GDK
of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 27
of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 27
of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 27 Benchmark gives 3x to 4x performance factor over Jackson and GSON
of JSON support for speed & efficiency • parser forked off the Boon JSON project • serializer carefully fine-tuned • Article on the parsing speed improvements • http://rick-hightower.blogspot.fr/2014/04/groovy-and-boon-provide-fastest-json.html 27
to JsonSlurperClassic • Additional parsing modes: • INDEX_OVERLAY: super fast for <2MB payloads • using a « parsing overlay » technique • CHARACTER_SOURCE: for >2MB payloads • implemented with sliding windows over readers • LAX: beyond the JSON spec, nice for configuration files • support single quotes, / and # comments • CHAR_BUFFER: general purpose 28
of Groovy’s « builders » • and particularly the MarkupBuilder class for generating arbitrary XML / HTML payloads • Compiled statically for fast template rendering • Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl • Custom base template class • ability to provide reusable methods across your templates 31
of Groovy’s « builders » • and particularly the MarkupBuilder class for generating arbitrary XML / HTML payloads • Compiled statically for fast template rendering • Internationalization aware • provide the desired Locale in the configuration object • usual suffix notation template_fr_FR.tpl • Custom base template class • ability to provide reusable methods across your templates 31 Spring Boot approved
{ cars.each { car(make: it.make, name: it.name) } } model = [cars: [ new Car(make: 'Peugeot', name: '508'), new Car(make: 'Toyota', name: 'Prius’) ]] Feed a model into your template
available • use createTypeCheckedModelTemplate() instead of createTemplate() • Advantages • get compilation errors • if a variable is not available • if you make mistakes in the code snippets • even faster templates 35
code Android apps! • use Groovy 2.4.0-beta-1+ • prefer @CompileStatic • Two great posts to get started: • http://melix.github.io/blog/2014/06/grooid.html • http://melix.github.io/blog/2014/06/grooid2.html 43
output • Works with templates bigger than 64K 47 import groovy.text.* def eng = new StreamingTemplateEngine() def tpl = eng.createTemplate ''' Hi ${name} ''' println tpl.make(name: 'Guillaume')
a macro module • https://github.com/groovy/groovy-core/pull/470 • Simplify creation of AST transformations • less boilerplate manipulating the Groovy AST API • more powerful and less limited than AstBuilder 49
verbose: 50 def someVariable = new ConstantExpression("xyz") def returnStatement = new ReturnStatement( new ConstructorCallExpression( ClassHelper.make(SomeCoolClass), new ArgumentListExpression(someVariable) ) )
uses Antlr v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs! 55
uses Antlr v2! • but version 3 and 4 are out • Groovy’s grammar evolved from a Java grammar • harder to fix and evolve, especially with Antlr v2 • Advantages • Start from a clean slate • Antlr 4 more tolerant and powerful regarding ambiguities • Time to clean some grammar & syntax warts! • Need to implement the Java 8 constructs! 55 A « Google Summer of Code » student helped kick start it
features to support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations 57
features to support • to keep saying Groovy / Java interoperability is awesome! • New in Java 8 • lambdas • method references • default methods in interfaces • stream API, date / time API • annotations on types & repeated annotations 57 Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
build upon JDK 7+ invoke dynamic • get Java-like performance even for dynamic code • Rationalize the sedimentation of meta-programming • more coherence, less corner cases & inconsistencies • Provide a notion of « realm » • shield users of « monkey patching » • finer-grained control of meta-programming reach • Private visibility anyone? 59