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

137d3908243acfc30e126615d59d4e6d?s=128

Guillaume Laforge

June 04, 2014
Tweet

Transcript

  1. Groovy in 2014 & beyond Guillaume Laforge Groovy Project Manager

    http://glaforge.appspot.com @glaforge
  2. None
  3. Stay up-to-date Groovy Weekly newsletter (Every Tuesday) http://bit.ly/groovy-weekly-subscribe

  4. Stay up-to-date Groovy Google+ page
 https://google.com/+groovy

  5. Stay up-to-date Groovy Google+ community http://bit.ly/g-community

  6. Agenda

  7. The Groovy roadmap… 2015 2014 2013 Groovy 2.3 Groovy 2.4

    Groovy 2.2 Groovy 3.0
  8. 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
  9. Groovy 3.0 ! • New Meta-Object Protocol ! • Invoke-dynamic

    based runtime ! • Rewritten language grammar with Antlr v4
  10. @YourTwitterHandle #DVXFR14{session hashtag} Groovy 2.3

  11. @YourTwitterHandle JDK 8 support

  12. 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));
  13. 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  }
  14. 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
  15. @YourTwitterHandle Traits

  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. trait  Named  {          String  name  

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

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

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

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

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

    }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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.)
  34. 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
  35. 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!
  36. 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
  37. 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.)
  38. 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?
  39. 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
  40. 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?
  41. 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
  42. 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?
  43. 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!
  44. 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?
  45. 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?
  46. 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!
  47. 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?
  48. 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?
  49. 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’
  50. 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
  51. 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?
  52. trait  Named  {          String  name  

    }   ! class  Animal  {}   class  NamedAnimal  implements  Named  {}   ! def  na  =  new  NamedAnimal(name:  'Felix')   ! assert  na.name  ==  'Felix' Traits: runtime implementation
  53. 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
  54. trait  Named  {          String  name  

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

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  56. 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
  57. trait  Named  {          String  name  

    }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  58. 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
  59. 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
  60. 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
  61. 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
  62. @YourTwitterHandle AST transforms

  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. New: @Sortable import  groovy.transform.*   ! @Sortable   class  Person

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

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

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

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

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

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

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

         def  run()  {          before()          internalRun()          after()      }   !    abstract  internalRun()   !    def  before()  {  println  'before'  }      def  after()    {  println  'after'    }   }
  79. @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'
  80. @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
  81. @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'
  82. @YourTwitterHandle NIO2 module

  83. 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()   …
  84. 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
  85. 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()   …
  86. @YourTwitterHandle JSON

  87. 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
  88. 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
  89. 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
  90. 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
  91. 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
  92. 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
  93. 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
  94. 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
  95. @YourTwitterHandle Markup template engine

  96. 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
  97. Markup template engine — the idea cars  {    

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

       cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  99. 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’)! ]]
  100. 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
  101. 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>
  102. 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
  103. 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>
  104. 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)
  105. 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'
  106. Markup template engine //  escaped  automatically   yield  'some  raw

     content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                
  107. 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(/*  ...  */)                      
  108. Markup template engine ! • Configuration options ! • declaration

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

    creation method ! ! ! ! • Or declare your model types in the template
  111. 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)
  112. 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")   }
  113. 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
  114. 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")   }
  115. @YourTwitterHandle Documentation overhaul

  116. GroovyDoc

  117. GroovyDoc

  118. GroovyDoc

  119. Groovy GDK documentation

  120. Groovy GDK documentation

  121. Brand new documentation

  122. Future groovy-lang.org website

  123. Future groovy-lang.org website

  124. Future groovy-lang.org website

  125. @YourTwitterHandle #DVXFR14{session hashtag} Groovy 3.0

  126. None
  127. @YourTwitterHandle MOP 2

  128. 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?
  129. @YourTwitterHandle Antlr v4 Grammar

  130. 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!
  131. 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
  132. @YourTwitterHandle Java 8 support

  133. 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
  134. 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
  135. @YourTwitterHandle #DVXFR14{session hashtag} Summary

  136. None
  137. Groovy rocks the JVM 
 since 2003!

  138. @YourTwitterHandle #DVXFR14{session hashtag} Q & A

  139. 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/