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

Groovy in 2014 and beyond at GR8Conf Europe 2014

Groovy in 2014 and beyond at GR8Conf Europe 2014

Groovy 2.3 coverage and what the future holds

Guillaume Laforge

June 04, 2014
Tweet

More Decks by Guillaume Laforge

Other Decks in Programming

Transcript

  1. Groovy 2.3 • JDK 8 runtime support • Traits •

    New and updates AST transformations • NIO2 module • JSON improvements & performance gains • New Markup template engine • Documentation overhaul
  2. Groovy 3.0 ! • New Meta-Object Protocol ! • Invoke-dynamic

    based runtime ! • Rewritten language grammar with Antlr v4
  3. JDK 8 support — closures & lambdas 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));
  4. JDK 8 support — closures & lambdas 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  }
  5. JDK 8 support — closures & lambdas 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
  6. 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 & compilation • class methods coming from traits are also visible from Java • Also possible to implement traits at runtime
  7. trait  FlyingAbility  {          String  fly()  {

     "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" Traits: a simple example
  8. trait  FlyingAbility  {          String  fly()  {

     "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" Traits: a simple example « trait », a new keyword for a new concept
  9. trait  FlyingAbility  {          String  fly()  {

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

     "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" Traits: a simple example the fly() method from the trait is available
  11. trait  FlyingAbility  {          String  fly()  {

     "I'm  flying!"  }   }   ! class  Bird  implements  FlyingAbility  {}   def  b  =  new  Bird()   ! assert  b.fly()  ==  "I'm  flying!" Traits: a simple example
  12. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  13. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful a Groovy property
  14. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful implement the trait
  15. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful Groovy named argument constructor
  16. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful access the property
  17. trait  Named  {          String  name  

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  18. 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!" Traits: inheritance
  19. 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!" Traits: inheritance extend the Named trait
  20. 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!" Traits: inheritance access the name property
  21. 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!" Traits: inheritance implement the composite trait
  22. 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!" Traits: inheritance
  23. trait  FlyingAbility  {          String  fly()  {

     "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" Traits: multiple inheritance (+dyn.)
  24. trait  FlyingAbility  {          String  fly()  {

     "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" Traits: multiple inheritance (+dyn.) access a dynamic property
  25. trait  FlyingAbility  {          String  fly()  {

     "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" Traits: multiple inheritance (+dyn.) implements two traits!
  26. trait  FlyingAbility  {          String  fly()  {

     "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" Traits: multiple inheritance (+dyn.) dynamic ‘name’ property interpolated
  27. trait  FlyingAbility  {          String  fly()  {

     "I'm  a  flying  $name!"  }   }   ! trait  Named  {  String  name  }   ! class  Bird  implements  Named,  FlyingAbility  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri'   assert  b.fly()  ==  "I'm  a  flying  Colibri!" Traits: multiple inheritance (+dyn.)
  28. 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' Traits: what about conflicts?
  29. 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' Traits: what about conflicts? two surf() methods
  30. 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' Traits: what about conflicts?
  31. 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' Traits: what about conflicts? extending a class and implementing the two traits
  32. 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' Traits: what about conflicts?
  33. 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' Traits: what about conflicts? last declared trait wins!
  34. 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' Traits: what about conflicts?
  35. 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' Traits: what about conflicts?
  36. 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' Traits: what about conflicts? reverse the order!
  37. 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' Traits: what about conflicts?
  38. 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' Traits: what about conflicts?
  39. 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' Traits: what about conflicts? Be explicit! Override surf() 
 & use ‘super’
  40. 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' Traits: what about conflicts? Your class method takes precedence over the traits
  41. 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' Traits: what about conflicts?
  42. trait  Named  {          String  name  

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation
  43. trait  Named  {          String  name  

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation Somewhat artificial to have to create an intermediary class to get named animals
  44. trait  Named  {          String  name  

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation
  45. trait  Named  {          String  name  

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  46. trait  Named  {          String  name  

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation Runtime trait, 
 with Groovy’s usual coercion mechanism
  47. trait  Named  {          String  name  

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  48. 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!' Traits: runtime implementation
  49. 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!' Traits: runtime implementation Implement several traits at once, at runtime
  50. 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!' Traits: runtime implementation
  51. Traits: miscellaneous • Traits can… ! • have private fields

    and methods • have abstract methods • implement interfaces • extend other traits or implement several traits • be statically type checked and compiled
  52. New: @TailRecursive 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
  53. New: @TailRecursive 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
  54. New: @TailRecursive 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
  55. New: @TailRecursive 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
  56. New: @TailRecursive 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
  57. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

     {          String  lastName          String  firstName          int  age   }
  58. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

     {          String  lastName          String  firstName          int  age   } Makes the class Comparable by multiple Comparators
  59. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

     {          String  lastName          String  firstName          int  age   } First compare by lastName, then by firstName, etc.
  60. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

     {          String  lastName          String  firstName          int  age   } You can also specify ‘includes’ / ‘excludes’ properties
  61. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

     {          String  lastName          String  firstName          int  age   }
  62. @BaseScript improvements abstract  class  CustomBase  extends  Script  {    

         int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  63. @BaseScript improvements 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
  64. @BaseScript improvements 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
  65. @BaseScript improvements abstract  class  CustomBase  extends  Script  {    

         int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42 In 2.3, ability to put the annotation on imports & package
  66. @BaseScript improvements abstract  class  CustomBase  extends  Script  {    

         int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  67. @BaseScript custom abstract method abstract  class  CustomBase  extends  Script  {

         def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   }
  68. @BaseScript custom abstract method 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. @BaseScript custom abstract method 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
  70. @BaseScript custom abstract method 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'
  71. JDK 7+ NIO2 module • All the familiar methods on

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

    File 
 retrofitted on Path as well 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
  73. JDK 7+ NIO2 module • All the familiar methods on

    File 
 retrofitted on Path as well path.withReader  {  Reader  r  -­‐>  ...  }   path.eachLine  {  String  line  -­‐>  ...  }   path.eachFileRecurse  {  Path  p  -­‐>  ...  }   path  <<  'some  content'   path  <<  bytes   path.readLines()   …
  74. 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
  75. 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
  76. 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 Benchmark gives 3x to 4x performance factor 
 over Jackson and GSON
  77. 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
  78. 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
  79. JsonSlurper for configuration files 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. JsonSlurper for configuration files 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
  81. JsonSlurper for configuration files 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
  82. 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
  83. Markup template engine — the idea cars  {    

       cars.each  {                car(make:  it.make,  name:  it.name)        }   }
  84. Markup template engine — the idea cars  {    

       cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  85. Markup template engine — the idea cars  {    

       cars.each  {                car(make:  it.make,  name:  it.name)        }   } model = [cars: [! new Car(make: 'Peugeot', name: '508'), ! new Car(make: 'Toyota', name: 'Prius’)! ]]
  86. Markup template engine — the idea 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
  87. Markup template engine — the idea 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>
  88. Markup template engine — the idea 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
  89. Markup template engine — the idea 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>
  90. Markup template engine — in action 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)
  91. Markup template engine — includes //  include  another  template  

    include  template:  'foo.tpl'           //  include  raw  content   include  unescaped:  'raw.txt'   ! //  escape  &  include   include  escaped:  'to_escape.txt'
  92. Markup template engine //  escaped  automatically   yield  'some  raw

     content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                
  93. Markup template engine //  escaped  automatically   yield  'some  raw

     content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                 //  <!-­‐-­‐comment-­‐-­‐>   comment  'comment'                 ! //  adds  new  lines   newLine()                                 ! //  process.  instruct.   pi(/*  ...  */)                      
  94. Markup template engine ! • Configuration options ! • declaration

    encoding ! • expand empty elements ! • use double quotes ! • newline string ! ! ! ! ! ! ! • auto escape ! • auto indent ! • base template class ! • locale
  95. 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
  96. Markup template engine — static! • With typed check model

    creation method ! ! ! ! • Or declare your model types in the template
  97. Markup template engine — static! • With typed check model

    creation method ! ! ! ! • Or declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes)
  98. Markup template engine — static! • With typed check model

    creation method ! ! ! ! • Or declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  99. Markup template engine — static! • With typed check model

    creation method ! ! ! ! • Or declare your model types in the template 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
  100. Markup template engine — static! • With typed check model

    creation method ! ! ! ! • Or declare your model types in the template def  modelTypes  =  [cars:  "List<Car>"]   ! def  tmpl  =  engine.      createTypeCheckedModelTemplate(
            "page.tpl",  modelTypes) modelTypes  =  {          List<Car>  cars   }   ! cars.each  {  car  -­‐>          p("Car  name:  $car.name")   }
  101. 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?
  102. 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!
  103. 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! A « Google Summer of Code » student to help
  104. 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
  105. 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 Groovy had already: closures, method pointers, mixins, enriched collection & time APIs
  106. Image credits / Creative Commons • Rue pavée — By-Nc-Sa

    • http://www.flickr.com/photos/22914687@N05/4957591422/sizes/l/ • Sous la Tour Eiffel — By-Nc-Sa • http://www.flickr.com/photos/stewiedewie/244850735/sizes/l/in/photostream/ • Sous le pont — By-Nc-Nd • http://www.landscape-photo.net/displayimage.php?pid=5194 • Paris Metro - By-Nc-Sa • http://www.flickr.com/photos/22914687@N05/6317047263/sizes/l/