Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Groovy in 2014 and beyond -- Devoxx 2014

Groovy in 2014 and beyond -- Devoxx 2014

With 3 million downloads last year, Groovy still clearly leads the pack of alternative languages on the JVM, but it's not resting on its laurels. The latest Groovy 2.3 release is pack full of useful new features and performance improvements. In particular, Groovy now supports the concept of "traits" for elegantly composing behaviors. Its JSON support is now the most performant among all the JSON libraries available to date. Groovy 2.3 introduces a new markup-based template engine, new code transformations, and much more. In this session, Groovy project lead Guillaume Laforge will guide you through the latest advancements of the Groovy programming language, and will tell you what's cooking for the next releases!

Guillaume Laforge

November 14, 2014
Tweet

More Decks by Guillaume Laforge

Other Decks in Programming

Transcript

  1. @glaforge #devoxx #groovylang The Groovy roadmap 3 2015 2014 2013

    Groovy 2.3 Groovy 2.4 Groovy 2.2 Groovy 2.5 ? Groovy 3.0 ?
  2. @glaforge #devoxx #groovylang JDK 8 support — closures vs lambdas

    6 IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));   Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it));
  3. @glaforge #devoxx #groovylang JDK 8 support — closures vs lambdas

    6 IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));   Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it)); IntStream.range(1,  100).forEach  {  println  it  }   Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  }
  4. @glaforge #devoxx #groovylang JDK 8 support — closures vs lambdas

    6 IntStream.range(1,  100).forEach(s  -­‐>                                                System.out.println(s));   Files.lines(Paths.get('README.adoc'))            .map(it  -­‐>  it.toUpperCase())            .forEach(it  -­‐>  System.out.println(it)); IntStream.range(1,  100).forEach  {  println  it  }   Files.lines(Paths.get('README.adoc'))            .map  {  it.toUpperCase()  }            .forEach  {  println  it  } Use Groovy closures wherever you pass lambdas in Java 8
  5. @glaforge #devoxx #groovylang Traits • Like interfaces, but with method

    bodies • 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
  6. @glaforge #devoxx #groovylang Traits: a simple example 9 trait  FlyingAbility

     {          String  fly()  {  "I'm  flying!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   assert  b.fly()  ==  "I'm  flying!"
  7. @glaforge #devoxx #groovylang Traits: a simple example 9 trait  FlyingAbility

     {          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
  8. @glaforge #devoxx #groovylang Traits: a simple example 9 trait  FlyingAbility

     {          String  fly()  {  "I'm  flying!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   assert  b.fly()  ==  "I'm  flying!" a class 
 « implements »
 a trait
  9. @glaforge #devoxx #groovylang Traits: a simple example 9 trait  FlyingAbility

     {          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
  10. @glaforge #devoxx #groovylang Traits: a simple example 9 trait  FlyingAbility

     {          String  fly()  {  "I'm  flying!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   assert  b.fly()  ==  "I'm  flying!"
  11. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'
  12. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri' a Groovy property
  13. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri' implement the trait
  14. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri' Groovy named argument constructor
  15. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri' access the property
  16. @glaforge #devoxx #groovylang Traits: stateful 10 trait  Named  {  

           String  name   }   class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'
  17. @glaforge #devoxx #groovylang Traits: inheritance 11 trait  Named  {  String

     name  }   trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  18. @glaforge #devoxx #groovylang Traits: inheritance 11 trait  Named  {  String

     name  }   trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" extend the Named trait
  19. @glaforge #devoxx #groovylang Traits: inheritance 11 trait  Named  {  String

     name  }   trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" access the name property
  20. @glaforge #devoxx #groovylang Traits: inheritance 11 trait  Named  {  String

     name  }   trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" implement the composite trait
  21. @glaforge #devoxx #groovylang Traits: inheritance 11 trait  Named  {  String

     name  }   trait  FlyingAbility  extends  Named  {          String  fly()  {  "I'm  a  flying  ${name}!"  }   }   class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!"
  22. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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'
  23. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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' two surf() methods
  24. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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'
  25. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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
  26. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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'
  27. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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' last declared trait wins!
  28. @glaforge #devoxx #groovylang Traits: what about conflicts? 12 trait  KiteSurfer

     {  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'
  29. @glaforge #devoxx #groovylang Traits: what about conflicts? 13 trait  KiteSurfer

     {  String  surf()  {  'kite'  }  }   trait  WebSurfer    {  String  surf()  {    'web'  }  }   class  Person  {  String  name  }   class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   def  h  =  new  Hipster()   assert  h.surf()  ==  'kite'
  30. @glaforge #devoxx #groovylang Traits: what about conflicts? 13 trait  KiteSurfer

     {  String  surf()  {  'kite'  }  }   trait  WebSurfer    {  String  surf()  {    'web'  }  }   class  Person  {  String  name  }   class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   def  h  =  new  Hipster()   assert  h.surf()  ==  'kite' reverse the order!
  31. @glaforge #devoxx #groovylang Traits: what about conflicts? 13 trait  KiteSurfer

     {  String  surf()  {  'kite'  }  }   trait  WebSurfer    {  String  surf()  {    'web'  }  }   class  Person  {  String  name  }   class  Hipster  extends  Person                        implements  WebSurfer,  KiteSurfer  {}   def  h  =  new  Hipster()   assert  h.surf()  ==  'kite'
  32. @glaforge #devoxx #groovylang Traits: what about conflicts? 14 trait  KiteSurfer

     {  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'
  33. @glaforge #devoxx #groovylang Traits: what about conflicts? 14 trait  KiteSurfer

     {  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' Be explicit! Override surf() 
 & use ‘super’
  34. @glaforge #devoxx #groovylang Traits: what about conflicts? 14 trait  KiteSurfer

     {  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
  35. @glaforge #devoxx #groovylang Traits: what about conflicts? 14 trait  KiteSurfer

     {  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'
  36. @glaforge #devoxx #groovylang Traits: runtime implementation 15 trait  Named  {

             String  name   }   class  Animal  {}   class  NamedAnimal  implements  Named  {}   def  na  =  new  NamedAnimal(name:  'Felix')   assert  na.name  ==  'Felix'
  37. @glaforge #devoxx #groovylang Traits: runtime implementation 15 trait  Named  {

             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
  38. @glaforge #devoxx #groovylang Traits: runtime implementation 15 trait  Named  {

             String  name   }   class  Animal  {}   class  NamedAnimal  implements  Named  {}   def  na  =  new  NamedAnimal(name:  'Felix')   assert  na.name  ==  'Felix'
  39. @glaforge #devoxx #groovylang Traits: runtime implementation 16 trait  Named  {

             String  name   }   class  Animal  {}   def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix'
  40. @glaforge #devoxx #groovylang Traits: runtime implementation 16 trait  Named  {

             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
  41. @glaforge #devoxx #groovylang Traits: runtime implementation 16 trait  Named  {

             String  name   }   class  Animal  {}   def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix'
  42. @glaforge #devoxx #groovylang Traits: runtime implementation 17 trait  Named  {

     String  name  }   trait  Quacks  {          String  quack()  {  'Quack!'  }   }   class  Animal  {}   def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!'
  43. @glaforge #devoxx #groovylang Traits: runtime implementation 17 trait  Named  {

     String  name  }   trait  Quacks  {          String  quack()  {  'Quack!'  }   }   class  Animal  {}   def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!' Implement several traits at once, at runtime
  44. @glaforge #devoxx #groovylang Traits: runtime implementation 17 trait  Named  {

     String  name  }   trait  Quacks  {          String  quack()  {  'Quack!'  }   }   class  Animal  {}   def  na  =  new  Animal().withTraits  Named,  Quacks   na.name  =  'Daffy'   assert  na.name  ==  'Daffy'   assert  na.quack()  ==  'Quack!'
  45. @glaforge #devoxx #groovylang Type constraints on traits with @SelfType •

    Only apply a trait to some child classes 18 class  Component  {
        void  doSomething()  {}
 }
 
 @SelfType(Component)
 trait  ComponentDecorator  {
        void  logAndDoSomething()  {
                println  "Calling  doSomething()"
                doSomething()
        }
 }
  46. @glaforge #devoxx #groovylang New: @TailRecursive 20 import  groovy.transform.TailRecursive   @TailRecursive

      def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   assert  fact(1000)  >  10e2566
  47. @glaforge #devoxx #groovylang New: @TailRecursive 20 import  groovy.transform.TailRecursive   @TailRecursive

      def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   assert  fact(1000)  >  10e2566 Rewrites tail recursive friendly function serially
  48. @glaforge #devoxx #groovylang New: @TailRecursive 20 import  groovy.transform.TailRecursive   @TailRecursive

      def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   assert  fact(1000)  >  10e2566 Doesn’t blow up with a stack overflow error
  49. @glaforge #devoxx #groovylang New: @TailRecursive 20 import  groovy.transform.TailRecursive   @TailRecursive

      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
  50. @glaforge #devoxx #groovylang New: @TailRecursive 20 import  groovy.transform.TailRecursive   @TailRecursive

      def  fact(BigInteger  n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }   assert  fact(1000)  >  10e2566
  51. @glaforge #devoxx #groovylang New: @Sortable 21 import  groovy.transform.*   @Sortable

      class  Person  {          String  lastName          String  firstName          int  age   }
  52. @glaforge #devoxx #groovylang New: @Sortable 21 import  groovy.transform.*   @Sortable

      class  Person  {          String  lastName          String  firstName          int  age   } Makes the class Comparable by multiple Comparators
  53. @glaforge #devoxx #groovylang New: @Sortable 21 import  groovy.transform.*   @Sortable

      class  Person  {          String  lastName          String  firstName          int  age   } First compare by lastName, then by firstName, etc.
  54. @glaforge #devoxx #groovylang New: @Sortable 21 import  groovy.transform.*   @Sortable

      class  Person  {          String  lastName          String  firstName          int  age   } You can also specify ‘includes’ / ‘excludes’ properties
  55. @glaforge #devoxx #groovylang New: @Sortable 21 import  groovy.transform.*   @Sortable

      class  Person  {          String  lastName          String  firstName          int  age   }
  56. @glaforge #devoxx #groovylang New: @Builder for fluent APIs 22 import

     groovy.transform.builder.Builder
 
 @Builder
 class  Person  {
    String  firstName
    String  lastName
    int  age
 }
  57. @glaforge #devoxx #groovylang New: @Builder for fluent APIs 22 import

     groovy.transform.builder.Builder
 
 @Builder
 class  Person  {
    String  firstName
    String  lastName
    int  age
 } def  person  =  Person.builder()
                .firstName("Robert")
                .lastName("Lewandowski")
                .age(21)
                .build()
  58. @glaforge #devoxx #groovylang New: @Builder for fluent APIs 22 import

     groovy.transform.builder.Builder
 
 @Builder
 class  Person  {
    String  firstName
    String  lastName
    int  age
 } def  person  =  Person.builder()
                .firstName("Robert")
                .lastName("Lewandowski")
                .age(21)
                .build() Different implementation strategies available
  59. @glaforge #devoxx #groovylang New: @Builder for fluent APIs 22 import

     groovy.transform.builder.Builder
 
 @Builder
 class  Person  {
    String  firstName
    String  lastName
    int  age
 } def  person  =  Person.builder()
                .firstName("Robert")
                .lastName("Lewandowski")
                .age(21)
                .build()
  60. @glaforge #devoxx #groovylang @BaseScript improvements 23 abstract  class  CustomBase  extends

     Script  {          int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   assert  meaningOfLife  ==  42
  61. @glaforge #devoxx #groovylang @BaseScript improvements 23 abstract  class  CustomBase  extends

     Script  {          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
  62. @glaforge #devoxx #groovylang @BaseScript improvements 23 abstract  class  CustomBase  extends

     Script  {          int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   assert  meaningOfLife  ==  42 Define the base script class for this script
  63. @glaforge #devoxx #groovylang @BaseScript improvements 23 abstract  class  CustomBase  extends

     Script  {          int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   assert  meaningOfLife  ==  42 Ability to put the annotation on imports & package
  64. @glaforge #devoxx #groovylang @BaseScript improvements 23 abstract  class  CustomBase  extends

     Script  {          int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   assert  meaningOfLife  ==  42
  65. @glaforge #devoxx #groovylang @BaseScript custom abstract method 24 abstract  class

     CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }      abstract  internalRun()      def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   }
  66. @glaforge #devoxx #groovylang @BaseScript custom abstract method 24 abstract  class

     CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }      abstract  internalRun()      def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   println  'Hello'
  67. @glaforge #devoxx #groovylang @BaseScript custom abstract method 24 abstract  class

     CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }      abstract  internalRun()      def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   println  'Hello' You can define your own abstract method for script bodies
  68. @glaforge #devoxx #groovylang @BaseScript custom abstract method 24 abstract  class

     CustomBase  extends  Script  {      def  run()  {          before()          internalRun()          after()      }      abstract  internalRun()      def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   } import  groovy.transform.BaseScript   @BaseScript  CustomBase  script   println  'Hello'
  69. @glaforge #devoxx #groovylang JDK 7+ NIO2 module • All the

    familiar methods on File 
 retrofitted on Path as well 26 path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  70. @glaforge #devoxx #groovylang JDK 7+ NIO2 module • All the

    familiar methods on File 
 retrofitted on Path as well 26 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
  71. @glaforge #devoxx #groovylang JDK 7+ NIO2 module • All the

    familiar methods on File 
 retrofitted on Path as well 26 path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  72. @glaforge #devoxx #groovylang JSON parser / builder perf. increase •

    Re-implementation 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 28
  73. @glaforge #devoxx #groovylang JSON parser / builder perf. increase •

    Re-implementation 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 28
  74. @glaforge #devoxx #groovylang JSON parser / builder perf. increase •

    Re-implementation 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 28 Benchmark gives 3x to 4x performance factor 
 over Jackson and GSON
  75. @glaforge #devoxx #groovylang JSON parser / builder perf. increase •

    Re-implementation 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 28
  76. @glaforge #devoxx #groovylang New modes for parsing • Original JsonSlurper

    renamed 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 29
  77. @glaforge #devoxx #groovylang JsonSlurper for configuration files 30 import  groovy.json.*

      import  static  groovy.json.JsonParserType.*   def  parser  =  new  JsonSlurper().setType(LAX)   def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }   '''   assert  conf.environment  ==  'production'   assert  conf.server  ==  5
  78. @glaforge #devoxx #groovylang JsonSlurper for configuration files 30 import  groovy.json.*

      import  static  groovy.json.JsonParserType.*   def  parser  =  new  JsonSlurper().setType(LAX)   def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }   '''   assert  conf.environment  ==  'production'   assert  conf.server  ==  5 More tolerant parser: 
 single quotes, 
 non-quoted keys, 
 // and # comments, missing comas
  79. @glaforge #devoxx #groovylang JsonSlurper for configuration files 30 import  groovy.json.*

      import  static  groovy.json.JsonParserType.*   def  parser  =  new  JsonSlurper().setType(LAX)   def  conf  =  parser.parseText  '''          //  configuration  file          {                  //  no  quote  for  key,  single  quoted  value                  environment:  'production'                  #  pound-­‐style  comment                  'server':  5          }   '''   assert  conf.environment  ==  'production'   assert  conf.server  ==  5
  80. @glaforge #devoxx #groovylang Markup template engine • Based on the

    principles 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 32
  81. @glaforge #devoxx #groovylang Markup template engine • Based on the

    principles 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 32 Spring Boot approved
  82. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   }
  83. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  84. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [ new Car(make: 'Peugeot', name: '508'), new Car(make: 'Toyota', name: 'Prius’) ]]
  85. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        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
  86. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [ new Car(make: 'Peugeot', name: '508'), new Car(make: 'Toyota', name: 'Prius’) ]] <cars> <car make='Peugeot' name='508'/> <car make='Toyota' name='Prius'/> </cars>
  87. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [ new Car(make: 'Peugeot', name: '508'), new Car(make: 'Toyota', name: 'Prius’) ]] <cars> <car make='Peugeot' name='508'/> <car make='Toyota' name='Prius'/> </cars> Generate the XML output
  88. @glaforge #devoxx #groovylang Markup template engine — the idea 33

    cars  {        cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [ new Car(make: 'Peugeot', name: '508'), new Car(make: 'Toyota', name: 'Prius’) ]] <cars> <car make='Peugeot' name='508'/> <car make='Toyota' name='Prius'/> </cars>
  89. @glaforge #devoxx #groovylang Markup template engine — in action 34

    import  groovy.text.markup.*   def  config  =  new  TemplateConfiguration()   def  engine  =  new  MarkupTemplateEngine(config)   def  tmpl  =  engine.createTemplate('''          p("Hello  ${model.name}")   ''')   def  model  =  [name:  'World']   System.out  <<  tmpl.make(model)
  90. @glaforge #devoxx #groovylang Markup template engine — includes 35 //

     include  another  template   include  template:  'foo.tpl'           //  include  raw  content   include  unescaped:  'raw.txt'   //  escape  &  include   include  escaped:  'to_escape.txt'
  91. @glaforge #devoxx #groovylang Markup template engine — static! • Type-checked

    templates 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 36
  92. @glaforge #devoxx #groovylang Markup template engine — static! • With

    typed check model creation method 37 def  modelTypes  =  [cars:  "List<Car>"]   def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes)
  93. @glaforge #devoxx #groovylang Markup template engine — static! • With

    typed check model creation method 37 def  modelTypes  =  [cars:  "List<Car>"]   def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  94. @glaforge #devoxx #groovylang Markup template engine — static! • With

    typed check model creation method 37 def  modelTypes  =  [cars:  "List<Car>"]   def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   cars.each  {  car  -­‐>          p("Car  name:  $car.name")   } Works with createTemplate() too
  95. @glaforge #devoxx #groovylang Markup template engine — static! • With

    typed check model creation method 37 def  modelTypes  =  [cars:  "List<Car>"]   def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  96. @glaforge #devoxx #groovylang Android support • You can use Groovy

    to 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 44
  97. @glaforge #devoxx #groovylang New York Times — Getting Groovy with

    • New York Times Getting Groovy with Reactive Android 45
  98. @glaforge #devoxx #groovylang New York Times — Getting Groovy with

    • New York Times Getting Groovy with Reactive Android 45 http://bit.ly/nyt-groovy
  99. @glaforge #devoxx #groovylang Groovy Macros • Sergei Egorov wants to

    contribute 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 47
  100. @glaforge #devoxx #groovylang Groovy Macros • Authoring AST transformations can

    be verbose: 48 def  someVariable  =  new  ConstantExpression("xyz")   def  returnStatement  =  new  ReturnStatement(          new  ConstructorCallExpression(                  ClassHelper.make(SomeCoolClass),                  new  ArgumentListExpression(someVariable)          )   )
  101. @glaforge #devoxx #groovylang Groovy Macros • With Groovy Macros, it

    could be simpler: 49 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     }
  102. @glaforge #devoxx #groovylang Groovy Macros • With Groovy Macros, it

    could be simpler: 49 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     } Special « macro » command
  103. @glaforge #devoxx #groovylang Groovy Macros • With Groovy Macros, it

    could be simpler: 49 def  someVariable  =  macro  {  "xyz"  }   def  returnStatement  =  macro  {            new  SomeCoolClass($v{  someVariable  })     } Special « macro » command Quasi-quotation
  104. @glaforge #devoxx #groovylang Antlr v4 grammar • Problems • Groovy

    still 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! 53
  105. @glaforge #devoxx #groovylang Antlr v4 grammar • Problems • Groovy

    still 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! 53 A « Google Summer of Code » student helped kick start it
  106. @glaforge #devoxx #groovylang Java 8 support • Additional grammar &

    semantic 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 55
  107. @glaforge #devoxx #groovylang Java 8 support • Additional grammar &

    semantic 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 55 Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
  108. @glaforge #devoxx #groovylang Goals for the new MOP • Leverage

    & 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? 57
  109. @glaforge #devoxx #groovylang Image credits • Antwerp • http://www.visitflanders.in/binaries/IMG_7895.jpg, http://www.semindex.be/upload/SemIndex/images/Accommodation/

    23/4_zaal6_original.jpg • Antwerp central station • http://4.bp.blogspot.com/_4dEsCVlFCgA/S7horBAdM5I/AAAAAAAAALU/eXOhxk2ou-8/s1600/Antwerp+Station.jpg • Big rock • http://wallpaper.preview-reviews.com/12852-red-rocks-in-a-snowstorm • Android robot • http://crackberry.com/sites/crackberry.com/files/styles/large/public/topic_images/2013/ANDROID.png?itok=xhm7jaxS • Modern MOP • http://i933.photobucket.com/albums/ad179/autobin/Wonder%20Mop/wondermop4.jpg • Jason • http://static.comicvine.com/uploads/original/3/32405/1031312-jason_19_inch_figure_l.jpg • Jigsaw • http://www.psdgraphics.com/file/psd-jigsaw-icon.jpg • Many thanks • http://www.trys.ie/wp-content/uploads/2013/06/many-thanks.jpg 62