Groovy in 2014 and beyond at Devoxx France

Groovy in 2014 and beyond at Devoxx France

New presentation on all the new features of Groovy 2.3

137d3908243acfc30e126615d59d4e6d?s=128

Guillaume Laforge

April 18, 2014
Tweet

Transcript

  1. @glaforge #dvxgroovy Groovy en 2014 et au-delà… Guillaume Laforge Groovy

    Project Manager http://glaforge.appspot.com
  2. None
  3. Les Cast Codeurs

  4. Les Cast Codeurs 18:05 Miles Davis

  5. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Weekly newsletter • Every Tuesday ! • http://bit.ly/groovy-weekly- subscribe
  6. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Google+ page ! • https://plus.google.com/ +groovy
  7. @glaforge #dvxgroovy Stay up-to-date with all things Groovy ! •

    Groovy Google+ community ! • https://plus.google.com/ communities/ 105160926044623621768
  8. @YourTwitterHandle #DVXFR14{session hashtag} @glaforge #dvxgroovy A genda

  9. @glaforge #dvxgroovy The Groovy roadmap… 2015 2014 2013

  10. @glaforge #dvxgroovy The Groovy roadmap… 2015 2014 2013 Groovy 2.2

  11. @glaforge #dvxgroovy The Groovy roadmap… 2015 2014 2013 Groovy 2.3

    Groovy 2.2
  12. @glaforge #dvxgroovy The Groovy roadmap… 2015 2014 2013 Groovy 2.3

    Groovy 3.0 Groovy 2.2
  13. @glaforge #dvxgroovy 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
  14. @glaforge #dvxgroovy Groovy 3.0 ! • New Meta-Object Protocol !

    • Invoke-dynamic based runtime ! • Rewritten language grammar with Antlr v4
  15. @YourTwitterHandle #DVXFR14{session hashtag} @glaforge #dvxgroovy G roovy 2.3

  16. @YourTwitterHandle @glaforge #dvxgroovy JD K 8 support

  17. @YourTwitterHandle @glaforge #dvxgroovy Traits

  18. @glaforge #dvxgroovy 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
  19. @glaforge #dvxgroovy 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
  20. @glaforge #dvxgroovy 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
  21. @glaforge #dvxgroovy 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
  22. @glaforge #dvxgroovy 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
  23. @glaforge #dvxgroovy 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
  24. @glaforge #dvxgroovy trait  Named  {          String

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

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

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

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

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

     name   }   ! class  Bird  implements  Named  {}   def  b  =  new  Bird(name:  'Colibri')   ! assert  b.name  ==  'Colibri' Traits: stateful
  30. @glaforge #dvxgroovy 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
  31. @glaforge #dvxgroovy 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
  32. @glaforge #dvxgroovy 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
  33. @glaforge #dvxgroovy 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
  34. @glaforge #dvxgroovy 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
  35. @glaforge #dvxgroovy 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 (& dynamism)
  36. @glaforge #dvxgroovy 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 (& dynamism) access a dynamic property
  37. @glaforge #dvxgroovy 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 (& dynamism) implements two traits!
  38. @glaforge #dvxgroovy 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 (& dynamism) dynamic ‘name’ property interpolated
  39. @glaforge #dvxgroovy 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 (& dynamism)
  40. @glaforge #dvxgroovy 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. @glaforge #dvxgroovy 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
  42. @glaforge #dvxgroovy 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. @glaforge #dvxgroovy 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
  44. @glaforge #dvxgroovy 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. @glaforge #dvxgroovy 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!
  46. @glaforge #dvxgroovy 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?
  47. @glaforge #dvxgroovy 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. @glaforge #dvxgroovy 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!
  49. @glaforge #dvxgroovy 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?
  50. @glaforge #dvxgroovy 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?
  51. @glaforge #dvxgroovy 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’
  52. @glaforge #dvxgroovy 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
  53. @glaforge #dvxgroovy 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?
  54. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override
  55. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override ‘this’ is the ‘this’ of the class implementing the trait
  56. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override The default Object#toString() method always prevails, 
 in spite of the trait’s toString()
  57. @glaforge #dvxgroovy ! ! trait  CustomToString  {   !  

         String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  !=  'a  Foo  instance' Traits: forcing method override
  58. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override
  59. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override Use @ForceOverride to force the compiler to use the trait’s method
  60. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override If Foo had implemented toString(), Foo’s toString() would always win
  61. @glaforge #dvxgroovy import  groovy.transform.ForceOverride   ! trait  CustomToString  {  

           @ForceOverride          String  toString()  {                  "a  ${this.class.name}  instance"          }   }   ! class  Foo  implements  CustomToString  {}   ! assert  new  Foo().toString()  ==  'a  Foo  instance' Traits: forcing method override
  62. @glaforge #dvxgroovy trait  Named  {          String

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

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

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

     name   }   ! class  Animal  {}   ! ! def  na  =  new  Animal()  as  Named   na.name  =  'Felix'   assert  na.name  ==  'Felix' Traits: runtime implementation
  68. @glaforge #dvxgroovy 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
  69. @glaforge #dvxgroovy 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
  70. @glaforge #dvxgroovy 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
  71. @glaforge #dvxgroovy 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
  72. @YourTwitterHandle @glaforge #dvxgroovy A ST transform s

  73. @glaforge #dvxgroovy 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
  74. @glaforge #dvxgroovy 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
  75. @glaforge #dvxgroovy 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
  76. @glaforge #dvxgroovy 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
  77. @glaforge #dvxgroovy 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
  78. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

    class  Person  {          String  lastName          String  firstName          int  age   }
  79. @glaforge #dvxgroovy New: @Sortable import  groovy.transform.*   ! @Sortable  

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

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

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

    class  Person  {          String  lastName          String  firstName          int  age   }
  83. @glaforge #dvxgroovy @BaseScript improvements abstract  class  CustomBase  extends  Script  {

             int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  84. @glaforge #dvxgroovy @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
  85. @glaforge #dvxgroovy @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
  86. @glaforge #dvxgroovy @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
  87. @glaforge #dvxgroovy @BaseScript improvements abstract  class  CustomBase  extends  Script  {

             int  meaningOfLife  =  42   } @BaseScript(CustomBase)   import  groovy.transform.BaseScript   ! assert  meaningOfLife  ==  42
  88. @glaforge #dvxgroovy @BaseScript custom abstract method abstract  class  CustomBase  extends

     Script  {          def  run()  {                  before()                  internalRun()                  after()          }   !        abstract  internalRun()   !        def  before()  {  println  'before'  }          def  after()    {  println  'after'    }   }
  89. @glaforge #dvxgroovy @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'
  90. @glaforge #dvxgroovy @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
  91. @glaforge #dvxgroovy @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'
  92. @YourTwitterHandle @glaforge #dvxgroovy N IO 2 m odule

  93. @glaforge #dvxgroovy 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()   …
  94. @glaforge #dvxgroovy 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 methods
  95. @glaforge #dvxgroovy 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()   …
  96. @YourTwitterHandle @glaforge #dvxgroovy JSO N

  97. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  98. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  99. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  100. @glaforge #dvxgroovy JSON parser / builder performance increase • Re-implementation

    of JSON support for speed & efficiency • parser forked of 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
  101. @glaforge #dvxgroovy 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
  102. @glaforge #dvxgroovy 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
  103. @glaforge #dvxgroovy 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
  104. @glaforge #dvxgroovy 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
  105. @YourTwitterHandle @glaforge #dvxgroovy M arkup tem plate engine

  106. @glaforge #dvxgroovy 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
  107. @glaforge #dvxgroovy Markup template engine — the idea cars  {

           cars.each  {                car(make:  it.make,  name:  it.name)        }   }
  108. @glaforge #dvxgroovy Markup template engine — the idea cars  {

           cars.each  {                car(make:  it.make,  name:  it.name)        }   } Your template
  109. @glaforge #dvxgroovy 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’)! ]]
  110. @glaforge #dvxgroovy 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
  111. @glaforge #dvxgroovy 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>
  112. @glaforge #dvxgroovy 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
  113. @glaforge #dvxgroovy 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>
  114. @glaforge #dvxgroovy 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)
  115. @glaforge #dvxgroovy 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'
  116. @glaforge #dvxgroovy Markup template engine — useful methods //  escaped

     automatically   yield  'some  raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                
  117. @glaforge #dvxgroovy Markup template engine — useful methods //  escaped

     automatically   yield  'some  raw  content'   ! //  include  raw  content   yieldUnescaped  'content'   ! //  <?xml  version='1.0'?>   xmlDeclaration()                 //  <!-­‐-­‐comment-­‐-­‐>   comment  'comment'                 ! //  adds  new  lines   newLine()                                 ! //  processing  instructions   pi(/*  ...  */)                      
  118. @glaforge #dvxgroovy Markup template engine — configuration • Configuration options

    ! • declaration encoding ! • expand empty elements ! • use double quotes ! • newline string ! ! ! ! • auto escape ! • auto indent ! • base template class ! • locale
  119. @glaforge #dvxgroovy 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
  120. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 declare your model types in the template
  121. @glaforge #dvxgroovy Markup template engine — static! • With typed

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

    check model creation method ! ! ! ! ! • Alternative: 
 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")   }
  123. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 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
  124. @glaforge #dvxgroovy Markup template engine — static! • With typed

    check model creation method ! ! ! ! ! • Alternative: 
 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")   }
  125. @YourTwitterHandle @glaforge #dvxgroovy D ocum entation overhaul

  126. @glaforge #dvxgroovy GroovyDoc: new style

  127. @glaforge #dvxgroovy GroovyDoc: new style

  128. @glaforge #dvxgroovy GroovyDoc: new style

  129. @glaforge #dvxgroovy Groovy GDK documentation: new style

  130. @glaforge #dvxgroovy Groovy GDK documentation: new style

  131. @glaforge #dvxgroovy Brand new documentation with Asciidoctor

  132. @glaforge #dvxgroovy Future groovy-lang.org website

  133. @glaforge #dvxgroovy Future groovy-lang.org website

  134. @glaforge #dvxgroovy Future groovy-lang.org website

  135. @YourTwitterHandle #DVXFR14{session hashtag} @glaforge #dvxgroovy G roovy 3.0

  136. None
  137. @YourTwitterHandle @glaforge #dvxgroovy M O P 2

  138. @glaforge #dvxgroovy Goals for the new Meta-Object Protocol • Fully

    leverage and 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?
  139. @YourTwitterHandle @glaforge #dvxgroovy A ntlr v4 G ram m ar

  140. @glaforge #dvxgroovy 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!
  141. @glaforge #dvxgroovy 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 « Groovy Summer of Code » student to help
  142. @YourTwitterHandle @glaforge #dvxgroovy Java 8 support

  143. @glaforge #dvxgroovy Java 8 support • Additional grammar and 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
  144. @glaforge #dvxgroovy Java 8 support • Additional grammar and 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
  145. @YourTwitterHandle #DVXFR14{session hashtag} @glaforge #dvxgroovy Sum m ary

  146. None
  147. Groovy rocks the JVM 
 since 2003!

  148. @YourTwitterHandle #DVXFR14{session hashtag} @glaforge #dvxgroovy Q & A

  149. @glaforge #dvxgroovy Crédit image / 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/ ! • Slide template created by @glaforge, completed by @nmartignole for Devoxx FR2014