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

Groovy in 2014 and beyond -- Groovy Grails eXchange 2014

Groovy in 2014 and beyond -- Groovy Grails eXchange 2014

As usual, Guillaume Laforge will go through the latest developments of the Groovy programming language and will update you with what's going on, what's to come, and beyond the language itself.

Guillaume Laforge

December 11, 2014
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. @glaforge
    #groovylang
    Groovy
    in 2014
    & beyond
    Guillaume Laforge
    Groovy project manager

    View Slide

  2. #groovylang @glaforge
    Stay up-to-date
    Groovy Weekly newsletter (every Tuesday) 

    http://beta.groovy-lang.org/groovy-weekly.html
    2

    View Slide

  3. #groovylang @glaforge
    The Groovy roadmap
    3
    2015
    2014
    2013
    Groovy 2.3
    Groovy 2.4
    Groovy 2.2
    Groovy 2.5
    Groovy 3.0 ?

    View Slide

  4. @glaforge
    #groovylang
    Groovy 2.3

    View Slide

  5. @glaforge
    #groovylang
    JDK 8 support

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  9. @glaforge
    #groovylang
    Traits

    View Slide

  10. #groovylang @glaforge
    Traits
    • Like interfaces, but with method bodies
    • similar to Java 8 interface default methods
    • Elegant way to compose behavior
    • multiple inheritance without the « diamond » problem
    • Traits can also be stateful
    • traits can have properties like normal classes
    • Compatible with static typing and static compilation
    • class methods from traits also visible from Java classes
    • Also possible to implement traits at runtime
    8

    View Slide

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

    View Slide

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

    View Slide

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

    « implements »

    a trait

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. #groovylang @glaforge
    Traits: what about conflicts?
    12
    trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  
    trait  WebSurfer    {  String  surf()  {    'web'  }  }  
    class  Person  {  String  name  }  
    class  Hipster  extends  Person  
                         implements  KiteSurfer,  WebSurfer  {}  
    def  h  =  new  Hipster()  
    assert  h.surf()  ==  'web'
    extending a class and
    implementing the two traits

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    & use ‘super’

    View Slide

  39. #groovylang @glaforge
    Traits: what about conflicts?
    14
    trait  KiteSurfer  {  String  surf()  {  'kite'  }  }  
    trait  WebSurfer    {  String  surf()  {    'web'  }  }  
    class  Person  {  String  name  }  
    class  Hipster  extends  Person  
                         implements  WebSurfer,  KiteSurfer  {  
           String  surf()  {  KiteSurfer.super.surf()  }  
    }  
    def  h  =  new  Hipster()  
    assert  h.surf()  ==  'kite'
    Your class method takes
    precedence over the traits

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    with Groovy’s usual
    coercion mechanism

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  50. @glaforge
    #groovylang
    AST transforms

    View Slide

  51. #groovylang @glaforge
    New: @TailRecursive
    19
    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

    View Slide

  52. #groovylang @glaforge
    New: @TailRecursive
    19
    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

    View Slide

  53. #groovylang @glaforge
    New: @TailRecursive
    19
    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

    View Slide

  54. #groovylang @glaforge
    New: @TailRecursive
    19
    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

    View Slide

  55. #groovylang @glaforge
    New: @TailRecursive
    19
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  61. #groovylang @glaforge
    New: @Builder for fluent APIs
    21
    import  groovy.transform.builder.Builder


    @Builder

    class  Person  {

       String  firstName

       String  lastName

       int  age

    }

    View Slide

  62. #groovylang @glaforge
    New: @Builder for fluent APIs
    21
    import  groovy.transform.builder.Builder


    @Builder

    class  Person  {

       String  firstName

       String  lastName

       int  age

    }
    def  person  =  Person.builder()

                   .firstName("Robert")

                   .lastName("Lewandowski")

                   .age(21)

                   .build()

    View Slide

  63. #groovylang @glaforge
    New: @Builder for fluent APIs
    21
    import  groovy.transform.builder.Builder


    @Builder

    class  Person  {

       String  firstName

       String  lastName

       int  age

    }
    def  person  =  Person.builder()

                   .firstName("Robert")

                   .lastName("Lewandowski")

                   .age(21)

                   .build()
    Different implementation
    strategies available

    View Slide

  64. #groovylang @glaforge
    New: @Builder for fluent APIs
    21
    import  groovy.transform.builder.Builder


    @Builder

    class  Person  {

       String  firstName

       String  lastName

       int  age

    }
    def  person  =  Person.builder()

                   .firstName("Robert")

                   .lastName("Lewandowski")

                   .age(21)

                   .build()

    View Slide

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

    View Slide

  66. #groovylang @glaforge
    @BaseScript improvements
    22
    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

    View Slide

  67. #groovylang @glaforge
    @BaseScript improvements
    22
    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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  71. #groovylang @glaforge
    @BaseScript custom abstract method
    23
    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'

    View Slide

  72. #groovylang @glaforge
    @BaseScript custom abstract method
    23
    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

    View Slide

  73. #groovylang @glaforge
    @BaseScript custom abstract method
    23
    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'

    View Slide

  74. @glaforge
    #groovylang
    NIO2 module

    View Slide

  75. #groovylang @glaforge
    JDK 7+ NIO2 module
    • All the familiar methods on File 

    retrofitted on Path as well
    25
    path.withReader  {  Reader  r  -­‐>  ...  }  
    path.eachLine  {  String  line  -­‐>  ...  }  
    path.eachFileRecurse  {  Path  p  -­‐>  ...  }  
    path  <<  'some  content'  
    path  <<  bytes  
    path.readLines()  

    View Slide

  76. #groovylang @glaforge
    JDK 7+ NIO2 module
    • All the familiar methods on File 

    retrofitted on Path as well
    25
    path.withReader  {  Reader  r  -­‐>  ...  }  
    path.eachLine  {  String  line  -­‐>  ...  }  
    path.eachFileRecurse  {  Path  p  -­‐>  ...  }  
    path  <<  'some  content'  
    path  <<  bytes  
    path.readLines()  

    Feature request to add all the
    java.nio.file.Files static utility
    methods as GDK

    View Slide

  77. #groovylang @glaforge
    JDK 7+ NIO2 module
    • All the familiar methods on File 

    retrofitted on Path as well
    25
    path.withReader  {  Reader  r  -­‐>  ...  }  
    path.eachLine  {  String  line  -­‐>  ...  }  
    path.eachFileRecurse  {  Path  p  -­‐>  ...  }  
    path  <<  'some  content'  
    path  <<  bytes  
    path.readLines()  

    View Slide

  78. @glaforge
    #groovylang
    JSON

    View Slide

  79. #groovylang @glaforge
    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
    27

    View Slide

  80. #groovylang @glaforge
    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
    27

    View Slide

  81. #groovylang @glaforge
    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
    27
    Benchmark gives 3x to 4x
    performance factor 

    over Jackson and GSON

    View Slide

  82. #groovylang @glaforge
    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
    27

    View Slide

  83. #groovylang @glaforge
    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
    28

    View Slide

  84. #groovylang @glaforge
    JsonSlurper for configuration files
    29
    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

    View Slide

  85. #groovylang @glaforge
    JsonSlurper for configuration files
    29
    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

    View Slide

  86. #groovylang @glaforge
    JsonSlurper for configuration files
    29
    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

    View Slide

  87. @glaforge
    #groovylang
    Markup template engine
    >

    View Slide

  88. #groovylang @glaforge
    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
    31

    View Slide

  89. #groovylang @glaforge
    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
    31
    Spring Boot
    approved

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  93. #groovylang @glaforge
    Markup template engine — the idea
    32
    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

    View Slide

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




    View Slide

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




    Generate the XML
    output

    View Slide

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




    View Slide

  97. #groovylang @glaforge
    Markup template engine — in action
    33
    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)

    View Slide

  98. #groovylang @glaforge
    Markup template engine — includes
    34
    //  include  another  template  
    include  template:  'foo.tpl'  
           
    //  include  raw  content  
    include  unescaped:  'raw.txt'  
    //  escape  &  include  
    include  escaped:  'to_escape.txt'

    View Slide

  99. #groovylang @glaforge
    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
    35

    View Slide

  100. #groovylang @glaforge
    Markup template engine — static!
    • With typed checked model creation method
    36

    View Slide

  101. #groovylang @glaforge
    Markup template engine — static!
    • With typed checked model creation method
    36
    def  modelTypes  =  [cars:  "List"]  
    def  tmpl  =  engine.  
       createTypeCheckedModelTemplate(

               "page.tpl",  modelTypes)

    View Slide

  102. #groovylang @glaforge
    Markup template engine — static!
    • With typed checked model creation method
    36
    def  modelTypes  =  [cars:  "List"]  
    def  tmpl  =  engine.  
       createTypeCheckedModelTemplate(

               "page.tpl",  modelTypes)
    modelTypes  =  {  
           List  cars  
    }  
    cars.each  {  car  -­‐>  
           p("Car  name:  $car.name")  
    }

    View Slide

  103. #groovylang @glaforge
    Markup template engine — static!
    • With typed checked model creation method
    36
    def  modelTypes  =  [cars:  "List"]  
    def  tmpl  =  engine.  
       createTypeCheckedModelTemplate(

               "page.tpl",  modelTypes)
    modelTypes  =  {  
           List  cars  
    }  
    cars.each  {  car  -­‐>  
           p("Car  name:  $car.name")  
    }
    Works with
    createTemplate() too

    View Slide

  104. #groovylang @glaforge
    Markup template engine — static!
    • With typed checked model creation method
    36
    def  modelTypes  =  [cars:  "List"]  
    def  tmpl  =  engine.  
       createTypeCheckedModelTemplate(

               "page.tpl",  modelTypes)
    modelTypes  =  {  
           List  cars  
    }  
    cars.each  {  car  -­‐>  
           p("Car  name:  $car.name")  
    }

    View Slide

  105. @glaforge
    #groovylang
    Documentation overhaul

    View Slide

  106. #groovylang @glaforge
    GroovyDoc
    38

    View Slide

  107. #groovylang @glaforge
    GroovyDoc
    38

    View Slide

  108. #groovylang @glaforge
    GroovyDoc
    38

    View Slide

  109. #groovylang @glaforge
    Groovy GDK documentation
    39

    View Slide

  110. #groovylang @glaforge
    Groovy GDK documentation
    39

    View Slide

  111. #groovylang @glaforge
    Brand new documentation
    40

    View Slide

  112. @glaforge
    #groovylang
    Groovy 2.4

    View Slide

  113. #groovylang @glaforge
    Beta groovy-lang.org website
    42

    View Slide

  114. #groovylang @glaforge
    Beta groovy-lang.org website
    42

    View Slide

  115. #groovylang @glaforge
    Beta groovy-lang.org website
    42

    View Slide

  116. #groovylang @glaforge
    Beta groovy-lang.org website
    42
    Notice the « improve
    this doc » button!

    View Slide

  117. #groovylang @glaforge
    Android support
    • You can use Groovy to code Android apps!
    • use Groovy 2.4.0-beta-1+
    • prefer @CompileStatic
    • Two great posts to get started:
    • http://melix.github.io/blog/2014/06/grooid.html
    • http://melix.github.io/blog/2014/06/grooid2.html
    43

    View Slide

  118. #groovylang @glaforge
    New York Times — Getting Groovy with
    44

    View Slide

  119. #groovylang @glaforge
    New York Times — Getting Groovy with
    44
    http://bit.ly/nyt-groovy

    View Slide

  120. #groovylang @glaforge
    Android support
    45

    View Slide

  121. #groovylang @glaforge
    Android support
    45
    Source code available:
    https://github.com/melix/gr8confagenda

    View Slide

  122. #groovylang @glaforge
    Type constraints on traits with @SelfType
    • Only apply a trait to some child classes
    46
    class  Component  {

           void  doSomething()  {}

    }


    @SelfType(Component)

    trait  ComponentDecorator  {

           void  logAndDoSomething()  {

                   println  "Calling  doSomething()"

                   doSomething()

           }

    }

    View Slide

  123. #groovylang @glaforge
    StreamingTemplateEngine
    • Uses writable closures to stream the output
    • Works with templates bigger than 64K
    47
    import  groovy.text.*  
    def  eng  =  new  StreamingTemplateEngine()  
    def  tpl  =  eng.createTemplate  '''

           Hi  ${name}

    '''  
    println  tpl.make(name:  'Guillaume')

    View Slide

  124. @glaforge
    #groovylang
    Groovy 2.5

    View Slide

  125. #groovylang @glaforge
    Groovy Macros
    • Sergei Egorov wants to contribute a macro module
    • https://github.com/groovy/groovy-core/pull/470
    • Simplify creation of AST transformations
    • less boilerplate manipulating the Groovy AST API
    • more powerful and less limited than AstBuilder
    49

    View Slide

  126. #groovylang @glaforge
    Groovy Macros
    • Authoring AST transformations can be verbose:
    50
    def  someVariable  =  new  ConstantExpression("xyz")  
    def  returnStatement  =  new  ReturnStatement(  
           new  ConstructorCallExpression(  
                   ClassHelper.make(SomeCoolClass),  
                   new  ArgumentListExpression(someVariable)  
           )  
    )

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  130. @glaforge
    #groovylang
    Groovy 3.0

    View Slide

  131. View Slide

  132. @glaforge
    #groovylang
    Rewriting the
    Groovy grammar
    with Antlr v4
    Antlr v4 Grammar

    View Slide

  133. #groovylang @glaforge
    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!
    55

    View Slide

  134. #groovylang @glaforge
    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!
    55
    A « Google Summer of Code »
    student helped kick start it

    View Slide

  135. @glaforge
    #groovylang
    Java 8 language support

    View Slide

  136. #groovylang @glaforge
    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
    57

    View Slide

  137. #groovylang @glaforge
    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
    57
    Groovy had already:
    closures, method pointers, mixins,
    enriched collection & time APIs

    View Slide

  138. @glaforge
    #groovylang
    MOP 2

    View Slide

  139. #groovylang @glaforge
    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?
    59

    View Slide

  140. @glaforge
    #groovylang
    Summary

    View Slide

  141. View Slide

  142. Groovy rocks the JVM 

    since 2003!

    View Slide

  143. @glaforge
    #groovylang
    Q & A

    View Slide

  144. View Slide

  145. #groovylang @glaforge
    Image credits
    • London:
    • http://www.excel-london.co.uk/media/26705/why-london-hero-shot.jpg
    • http://libertychurchlondon.com/wp-content/uploads/2013/01/london1.jpg
    • http://cdni.wired.co.uk/1920x1280/k_n/London_5.jpg
    • http://www.100percentoptical.com/images/2014/10/london.jpg
    • Big rock: http://wallpaper.preview-reviews.com/12852-red-rocks-in-a-snowstorm
    • Android robot: http://crackberry.com/sites/crackberry.com/files/styles/large/public/topic_images/2013/ANDROID.png?itok=xhm7jaxS
    • Modern MOP: http://i933.photobucket.com/albums/ad179/autobin/Wonder%20Mop/wondermop4.jpg
    • Jason: http://static.comicvine.com/uploads/original/3/32405/1031312-jason_19_inch_figure_l.jpg
    • Jigsaw: http://www.psdgraphics.com/file/psd-jigsaw-icon.jpg
    • Many thanks: http://www.trys.ie/wp-content/uploads/2013/06/many-thanks.jpg
    64

    View Slide