Groovy Update presentation at Groovy Grails eXchange 2013

Groovy Update presentation at Groovy Grails eXchange 2013

Update on the latest development, new features, of the Groovy programming language project

137d3908243acfc30e126615d59d4e6d?s=128

Guillaume Laforge

December 12, 2013
Tweet

Transcript

  1. Guillaume Laforge 
 @glaforge The Groovy Update

  2. Guillaume  Laforge Groovy project lead at . ! @glaforge

    http://glaforge.appspot.com
  3. None
  4. Groovy 2.2 Part 1

  5. Implicit closure coercion Java 8 style :-)

  6. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  }
  7. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  } « Functional » interface
  8. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  } « Functional » interface A bit verbose?
  9. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  } « Functional » interface A bit verbose? Implicit closure coercion
  10. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  } (it)  -­‐>  it  >  2 « Functional » interface A bit verbose? Implicit closure coercion
  11. @glaforge — Groovy Grails eXchange 2013 Implicit closure coercion !6

    interface  Predicate  {          boolean  test(something)   }   ! List  filter(List  l,  Predicate  p)  {          l.findAll  {  p.test(it)  }   }   ! filter([1,  2,  3,  4],  {  it  >  2  }  as  Predicate)   ! filter([1,  2,  3,  4],  {  it  >  2  })   ! filter([1,  2,  3,  4])  {  it  >  2  } (it)  -­‐>  it  >  2 « Functional » interface Works with single abstract method classes too A bit verbose? Implicit closure coercion
  12. AST transforms @Memoized @Log4j2

  13. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation •

    Piggypack on Closure’s own memoization support !8 import  groovy.transform.Memoized   ! @Memoized  int  expensiveOp(int  a,  int  b)  {          sleep  1000          return  a  +  b   }   ! expensiveOp(1,  2)   ! expensiveOp(1,  2)
  14. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation •

    Piggypack on Closure’s own memoization support !8 import  groovy.transform.Memoized   ! @Memoized  int  expensiveOp(int  a,  int  b)  {          sleep  1000          return  a  +  b   }   ! expensiveOp(1,  2)   ! expensiveOp(1,  2) First call takes 1 s
  15. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation •

    Piggypack on Closure’s own memoization support !8 import  groovy.transform.Memoized   ! @Memoized  int  expensiveOp(int  a,  int  b)  {          sleep  1000          return  a  +  b   }   ! expensiveOp(1,  2)   ! expensiveOp(1,  2) First call takes 1 s Subsequent calls return immediately from the cache
  16. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !9

    import  groovy.transform.Memoized   ! @Memoized   long  fib(long  n)  {          n  <  2  ?  1  :  fib(n-­‐1)  +  fib(n-­‐2)   }   ! fib(40)
  17. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !9

    import  groovy.transform.Memoized   ! @Memoized   long  fib(long  n)  {          n  <  2  ?  1  :  fib(n-­‐1)  +  fib(n-­‐2)   }   ! fib(40) Handy to cache recursive call results!
  18. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !9

    import  groovy.transform.Memoized   ! @Memoized   long  fib(long  n)  {          n  <  2  ?  1  :  fib(n-­‐1)  +  fib(n-­‐2)   }   ! fib(40) Handy to cache recursive call results! Instantaneous result
  19. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !10

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  20. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !11

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  21. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !12

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  22. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !13

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  23. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !14

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  24. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !15

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  25. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !16

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  26. @glaforge — Groovy Grails eXchange 2013 … … … @Memoized

    AST transformation !17 fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4)
  27. @glaforge — Groovy Grails eXchange 2013 … … … @Memoized

    AST transformation !17 fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) Already calculated, in cache!
  28. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !18

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  29. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !19

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  30. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !20

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  31. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !21

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) … … …
  32. @glaforge — Groovy Grails eXchange 2013 @Memoized AST transformation !21

    fib(7) fib(5) fib(6) fib(3) fib(4) fib(4) fib(5) fib(1) fib(2) fib(2) fib(3) fib(2) fib(3) fib(3) fib(4) Much less computation, no abysmal call stack … … …
  33. @glaforge — Groovy Grails eXchange 2013 Log4j2 @Log variant !22

    import  groovy.util.logging.Log4j2   ! @Log4j2   class  MyClass  {          void  doSomething()  {                  log.info  "did  something  groovy  today!"          }   }
  34. @glaforge — Groovy Grails eXchange 2013 Log4j2 @Log variant !22

    import  groovy.util.logging.Log4j2   ! @Log4j2   class  MyClass  {          void  doSomething()  {                  log.info  "did  something  groovy  today!"          }   } Just like our other logger implementations, but for Log4j2
  35. @glaforge — Groovy Grails eXchange 2013 Log4j2 @Log variant !22

    import  groovy.util.logging.Log4j2   ! @Log4j2   class  MyClass  {          void  doSomething()  {                  log.info  "did  something  groovy  today!"          }   } Just like our other logger implementations, but for Log4j2 Log, log, log away…
  36. @glaforge — Groovy Grails eXchange 2013 Choose which delegated methods

    to use !23 class  Event  {          @Delegate(excludes  =  ['after'])    Date  start          @Delegate(excludes  =  ['before'])  Date  end          String  description   }   ! def  today        =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! def  event  =  new  Event(description:  'Groovy  conference',                                                          start:  nextWeek,                                                              end:  nextWeek  +  2)   ! assert  event.before(nextWeek  +  1)   assert  !event.before(nextWeek  -­‐  1)   assert  !event.before(today)   ! assert  event.after(today)   assert  event.after(nextWeek  +  1)   assert  !event.after(nextWeek  +  3)
  37. @glaforge — Groovy Grails eXchange 2013 Choose which delegated methods

    to use !23 class  Event  {          @Delegate(excludes  =  ['after'])    Date  start          @Delegate(excludes  =  ['before'])  Date  end          String  description   }   ! def  today        =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! def  event  =  new  Event(description:  'Groovy  conference',                                                          start:  nextWeek,                                                              end:  nextWeek  +  2)   ! assert  event.before(nextWeek  +  1)   assert  !event.before(nextWeek  -­‐  1)   assert  !event.before(today)   ! assert  event.after(today)   assert  event.after(nextWeek  +  1)   assert  !event.after(nextWeek  +  3) Exclude certain methods from being delegated
  38. @glaforge — Groovy Grails eXchange 2013 Choose which delegated methods

    to use !23 class  Event  {          @Delegate(excludes  =  ['after'])    Date  start          @Delegate(excludes  =  ['before'])  Date  end          String  description   }   ! def  today        =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! def  event  =  new  Event(description:  'Groovy  conference',                                                          start:  nextWeek,                                                              end:  nextWeek  +  2)   ! assert  event.before(nextWeek  +  1)   assert  !event.before(nextWeek  -­‐  1)   assert  !event.before(today)   ! assert  event.after(today)   assert  event.after(nextWeek  +  1)   assert  !event.after(nextWeek  +  3) Exclude certain methods from being delegated Delegate to start date
  39. @glaforge — Groovy Grails eXchange 2013 Choose which delegated methods

    to use !23 class  Event  {          @Delegate(excludes  =  ['after'])    Date  start          @Delegate(excludes  =  ['before'])  Date  end          String  description   }   ! def  today        =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! def  event  =  new  Event(description:  'Groovy  conference',                                                          start:  nextWeek,                                                              end:  nextWeek  +  2)   ! assert  event.before(nextWeek  +  1)   assert  !event.before(nextWeek  -­‐  1)   assert  !event.before(today)   ! assert  event.after(today)   assert  event.after(nextWeek  +  1)   assert  !event.after(nextWeek  +  3) Exclude certain methods from being delegated Delegate to start date Delegate to end date
  40. Base script classes Delegation Annotation-driven base class DelegatingScript @DelegatesTo refinement

  41. @glaforge — Groovy Grails eXchange 2013 Annotation-driven base script class

    definition !25 import  groovy.transform.BaseScript   ! abstract  class  DeclaredBaseScript  extends  Script  {          int  meaningOfLife  =  42   }
  42. @glaforge — Groovy Grails eXchange 2013 Annotation-driven base script class

    definition !25 import  groovy.transform.BaseScript   ! abstract  class  DeclaredBaseScript  extends  Script  {          int  meaningOfLife  =  42   } Your own Script class extension
  43. @glaforge — Groovy Grails eXchange 2013 Annotation-driven base script class

    definition !25 import  groovy.transform.BaseScript   ! abstract  class  DeclaredBaseScript  extends  Script  {          int  meaningOfLife  =  42   } @BaseScript  DeclaredBaseScript  baseScript   ! assert  meaningOfLife  ==  42 Your own Script class extension
  44. @glaforge — Groovy Grails eXchange 2013 Annotation-driven base script class

    definition !25 import  groovy.transform.BaseScript   ! abstract  class  DeclaredBaseScript  extends  Script  {          int  meaningOfLife  =  42   } @BaseScript  DeclaredBaseScript  baseScript   ! assert  meaningOfLife  ==  42 Declare a variable annotated with @BaseScript, whose type is a subclass of Script Your own Script class extension
  45. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class • Special base script class to delegate method calls and property accesses to a custom object !26 name  =  "Guillaume"   sayHi() class  Person  {          String  name   !        void  sayHi()  {                  println  "Hi  $name"          }   }
  46. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class • Special base script class to delegate method calls and property accesses to a custom object !26 name  =  "Guillaume"   sayHi() class  Person  {          String  name   !        void  sayHi()  {                  println  "Hi  $name"          }   } Your script
  47. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class • Special base script class to delegate method calls and property accesses to a custom object !26 name  =  "Guillaume"   sayHi() class  Person  {          String  name   !        void  sayHi()  {                  println  "Hi  $name"          }   } Your script Delegate property access and method call to this custom class
  48. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class • Special base script class to delegate method calls and property accesses to a custom object !26 name  =  "Guillaume"   sayHi() class  Person  {          String  name   !        void  sayHi()  {                  println  "Hi  $name"          }   } Your script Delegate property access and method call to this custom class How do I do that?
  49. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume"
  50. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume" Specify DelegatingScript base class
  51. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume" Specify DelegatingScript base class Parse the script
  52. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume" Specify DelegatingScript base class Parse the script Define the delegate
  53. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume" Specify DelegatingScript base class Parse the script Define the delegate Run the script
  54. @glaforge — Groovy Grails eXchange 2013 DelegatingScript new base script

    class !27 def  cc  =  new  CompilerConfiguration()   cc.scriptBaseClass  =  DelegatingScript.class.name   ! def  sh  =  new  GroovyShell(cc)   def  script  =  sh.parse(file)   ! def  p  =  new  Person()   script.setDelegate(p)   script.run()   ! assert  p.name  ==  "Guillaume" Specify DelegatingScript base class Parse the script Define the delegate Run the script Be Happy!
  55. @glaforge — Groovy Grails eXchange 2013 @DelegatesTo with generics type

    tokens • @DelegatesTo help the type checker & IDEs provide better support for DSL using closure delegation !28 @groovy.transform.InheritConstructors   class  MyList  extends  LinkedList<String>  {}   ! public  <T>  Object  map(              @DelegatesTo.Target  List<T>  target,              @DelegatesTo(genericTypeIndex  =  0)  Closure  arg)  {          arg.delegate  =  target.join('')          arg()   }   ! def  test()  {          map(new  MyList(['f',  'o',  'o']))  {                  assert  toUpperCase()  ==  'FOO'          }   }
  56. @glaforge — Groovy Grails eXchange 2013 @DelegatesTo with generics type

    tokens • @DelegatesTo help the type checker & IDEs provide better support for DSL using closure delegation !28 @groovy.transform.InheritConstructors   class  MyList  extends  LinkedList<String>  {}   ! public  <T>  Object  map(              @DelegatesTo.Target  List<T>  target,              @DelegatesTo(genericTypeIndex  =  0)  Closure  arg)  {          arg.delegate  =  target.join('')          arg()   }   ! def  test()  {          map(new  MyList(['f',  'o',  'o']))  {                  assert  toUpperCase()  ==  'FOO'          }   } We want to delegate to the token type T
  57. @glaforge — Groovy Grails eXchange 2013 @DelegatesTo with generics type

    tokens • @DelegatesTo help the type checker & IDEs provide better support for DSL using closure delegation !28 @groovy.transform.InheritConstructors   class  MyList  extends  LinkedList<String>  {}   ! public  <T>  Object  map(              @DelegatesTo.Target  List<T>  target,              @DelegatesTo(genericTypeIndex  =  0)  Closure  arg)  {          arg.delegate  =  target.join('')          arg()   }   ! def  test()  {          map(new  MyList(['f',  'o',  'o']))  {                  assert  toUpperCase()  ==  'FOO'          }   } We want to delegate to the token type T We define the index of the type token
  58. @glaforge — Groovy Grails eXchange 2013 @DelegatesTo with generics type

    tokens • @DelegatesTo help the type checker & IDEs provide better support for DSL using closure delegation !28 @groovy.transform.InheritConstructors   class  MyList  extends  LinkedList<String>  {}   ! public  <T>  Object  map(              @DelegatesTo.Target  List<T>  target,              @DelegatesTo(genericTypeIndex  =  0)  Closure  arg)  {          arg.delegate  =  target.join('')          arg()   }   ! def  test()  {          map(new  MyList(['f',  'o',  'o']))  {                  assert  toUpperCase()  ==  'FOO'          }   } We want to delegate to the token type T We define the index of the type token This is String’s toUpperCase() method
  59. Type checking extensions Precompilation New events Dynamic calls

  60. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    precompilation • Custom type checking extensions can work with compiled extensions as well !30 @TypeChecked(extensions  =  'com.enterprise.MyDslExtension')   void  myBusinessMethod()  {          //  ...   }
  61. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    precompilation • Custom type checking extensions can work with compiled extensions as well !30 @TypeChecked(extensions  =  'com.enterprise.MyDslExtension')   void  myBusinessMethod()  {          //  ...   } Fully qualified name of the extension class
  62. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    precompilation • Custom type checking extensions can work with compiled extensions as well !30 @TypeChecked(extensions  =  'com.enterprise.MyDslExtension')   void  myBusinessMethod()  {          //  ...   } Fully qualified name of the extension class Here, your statically type checked DSL code!
  63. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   }
  64. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   } incompatibleReturnType event
  65. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   } incompatibleReturnType event The referred return type is incompatible with the method’s declared return type
  66. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   } incompatibleReturnType event The referred return type is incompatible with the method’s declared return type Assume that if the inferred return type is String, then it’s correct (the DSL handles it)
  67. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !32 ambiguousMethods  {  methods,  origin  -­‐>          methods.find  {  it.parameters.any  {                    it.type  ==  classNodeFor(Integer)  }            }   }
  68. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !32 ambiguousMethods  {  methods,  origin  -­‐>          methods.find  {  it.parameters.any  {                    it.type  ==  classNodeFor(Integer)  }            }   } ambiguousMethods event
  69. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !32 ambiguousMethods  {  methods,  origin  -­‐>          methods.find  {  it.parameters.any  {                    it.type  ==  classNodeFor(Integer)  }            }   } ambiguousMethods event If one of the methods takes an Integer argument, pick this one
  70. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    dynamic calls • New makeDynamic() method to make calls dynamic !33 methodNotFound  {  receiver,  name,  argumentList,  argTypes,  call  -­‐>          return  makeDynamic(call,  int_TYPE)   }   ! unresolvedProperty  {  pexp  -­‐>          def  lhs  =  getType(pexp.objectExpression)          if  (lhs==classNodeFor(MetaClass))  {                  makeDynamic(pexp,  CLOSURE_TYPE)          }  else  {                  makeDynamic(pexp,  int_TYPE)          }   }   ! unresolvedAttribute  {  pexp  -­‐>          makeDynamic(pexp,  int_TYPE)   }   ! unresolvedVariable  {  var  -­‐>          makeDynamic(var,  int_TYPE)   }
  71. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    dynamic calls • New makeDynamic() method to make calls dynamic !33 methodNotFound  {  receiver,  name,  argumentList,  argTypes,  call  -­‐>          return  makeDynamic(call,  int_TYPE)   }   ! unresolvedProperty  {  pexp  -­‐>          def  lhs  =  getType(pexp.objectExpression)          if  (lhs==classNodeFor(MetaClass))  {                  makeDynamic(pexp,  CLOSURE_TYPE)          }  else  {                  makeDynamic(pexp,  int_TYPE)          }   }   ! unresolvedAttribute  {  pexp  -­‐>          makeDynamic(pexp,  int_TYPE)   }   ! unresolvedVariable  {  var  -­‐>          makeDynamic(var,  int_TYPE)   } Unresolved methods, properties, attributes, or variables can be made dynamic
  72. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    dynamic calls • New makeDynamic() method to make calls dynamic !33 methodNotFound  {  receiver,  name,  argumentList,  argTypes,  call  -­‐>          return  makeDynamic(call,  int_TYPE)   }   ! unresolvedProperty  {  pexp  -­‐>          def  lhs  =  getType(pexp.objectExpression)          if  (lhs==classNodeFor(MetaClass))  {                  makeDynamic(pexp,  CLOSURE_TYPE)          }  else  {                  makeDynamic(pexp,  int_TYPE)          }   }   ! unresolvedAttribute  {  pexp  -­‐>          makeDynamic(pexp,  int_TYPE)   }   ! unresolvedVariable  {  var  -­‐>          makeDynamic(var,  int_TYPE)   } Unresolved methods, properties, attributes, or variables can be made dynamic Use with care!
  73. GDK improvements MrHaki 
 approved!

  74. @glaforge — Groovy Grails eXchange 2013 Remove part of strings

    with a regex !35 assert  ('Hello  Groovy  world!'  -­‐  ~/\s+Gr\w+/)                            ==  'Hello  world!'
  75. @glaforge — Groovy Grails eXchange 2013 Remove part of strings

    with a regex !35 assert  ('Hello  Groovy  world!'  -­‐  ~/\s+Gr\w+/)                            ==  'Hello  world!' A String
  76. @glaforge — Groovy Grails eXchange 2013 Remove part of strings

    with a regex !35 assert  ('Hello  Groovy  world!'  -­‐  ~/\s+Gr\w+/)                            ==  'Hello  world!' A String A Pattern
  77. @glaforge — Groovy Grails eXchange 2013 Remove part of strings

    with a regex !35 assert  ('Hello  Groovy  world!'  -­‐  ~/\s+Gr\w+/)                            ==  'Hello  world!' A String A Pattern Matched string fragment removed!
  78. @glaforge — Groovy Grails eXchange 2013 Lots of new methods

    for Iterables !36 class  Counter  implements  Iterable  {          private  Integer  counter  =  0          Iterator  iterator()  {                  [hasNext:  {  counter  <=  10  },                          next:  {  counter++  }]  as  Iterator          }   }
  79. @glaforge — Groovy Grails eXchange 2013 Lots of new methods

    for Iterables !36 class  Counter  implements  Iterable  {          private  Integer  counter  =  0          Iterator  iterator()  {                  [hasNext:  {  counter  <=  10  },                          next:  {  counter++  }]  as  Iterator          }   } assert  new  Counter().sum()  ==  55   assert  new  Counter().min()  ==  0   assert  new  Counter().max()  ==  10   assert  new  Counter().count(2)  ==  1   assert  new  Counter().count  {  it  %  2  ==  0  }  ==  6   assert  new  Counter().collectMany  {  [it  *  2]  }  ==                                  [0,  2,  4,  6,  8,  10,  12,  14,  16,  18,  20]   assert  new  Counter().groupBy  {  it  %  2  ==  0  ?  'even'  :  'odd'  }  ==                                  [even:[0,  2,  4,  6,  8,  10],  odd:[1,  3,  5,  7,  9]]
  80. @glaforge — Groovy Grails eXchange 2013 Lots of new methods

    for Iterables !36 class  Counter  implements  Iterable  {          private  Integer  counter  =  0          Iterator  iterator()  {                  [hasNext:  {  counter  <=  10  },                          next:  {  counter++  }]  as  Iterator          }   } assert  new  Counter().sum()  ==  55   assert  new  Counter().min()  ==  0   assert  new  Counter().max()  ==  10   assert  new  Counter().count(2)  ==  1   assert  new  Counter().count  {  it  %  2  ==  0  }  ==  6   assert  new  Counter().collectMany  {  [it  *  2]  }  ==                                  [0,  2,  4,  6,  8,  10,  12,  14,  16,  18,  20]   assert  new  Counter().groupBy  {  it  %  2  ==  0  ?  'even'  :  'odd'  }  ==                                  [even:[0,  2,  4,  6,  8,  10],  odd:[1,  3,  5,  7,  9]] Collections are also Iterable
  81. @glaforge — Groovy Grails eXchange 2013 @Immutable with copyWith() method

    !37 import  groovy.transform.Immutable   ! @Immutable(copyWith  =  true)   class  User  {          String  name          String  email   }   ! def  jdEx  =  new  User('John  Doe',  'jdoe@example.com')   ! def  jdGmail  =  jdEx.copyWith(email:  'jdoe@gmail.com')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  'jdoe@gmail.com'   }
  82. @glaforge — Groovy Grails eXchange 2013 @Immutable with copyWith() method

    !37 import  groovy.transform.Immutable   ! @Immutable(copyWith  =  true)   class  User  {          String  name          String  email   }   ! def  jdEx  =  new  User('John  Doe',  'jdoe@example.com')   ! def  jdGmail  =  jdEx.copyWith(email:  'jdoe@gmail.com')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  'jdoe@gmail.com'   } Specify you want the copyWith() method
  83. @glaforge — Groovy Grails eXchange 2013 @Immutable with copyWith() method

    !37 import  groovy.transform.Immutable   ! @Immutable(copyWith  =  true)   class  User  {          String  name          String  email   }   ! def  jdEx  =  new  User('John  Doe',  'jdoe@example.com')   ! def  jdGmail  =  jdEx.copyWith(email:  'jdoe@gmail.com')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  'jdoe@gmail.com'   } Specify you want the copyWith() method New immutable user with a different email
  84. @glaforge — Groovy Grails eXchange 2013 set() & copyWith() for

    Date & Calendar !38 import  static  java.util.Calendar.DECEMBER   ! def  date  =  new  Date().clearTime()   date.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  yearLater  =  date.copyWith(year:  2014)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '25-­‐12-­‐2014'
  85. @glaforge — Groovy Grails eXchange 2013 set() & copyWith() for

    Date & Calendar !38 import  static  java.util.Calendar.DECEMBER   ! def  date  =  new  Date().clearTime()   date.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  yearLater  =  date.copyWith(year:  2014)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '25-­‐12-­‐2014' Mutate
  86. @glaforge — Groovy Grails eXchange 2013 set() & copyWith() for

    Date & Calendar !38 import  static  java.util.Calendar.DECEMBER   ! def  date  =  new  Date().clearTime()   date.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  yearLater  =  date.copyWith(year:  2014)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '25-­‐12-­‐2014' def  cal  =  Calendar.instance   cal.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  newCalendar  =  cal.copyWith(date:  15)   assert  newCalendar.format('dd-­‐MM-­‐yyyy')  ==  '15-­‐12-­‐2013' Mutate
  87. @glaforge — Groovy Grails eXchange 2013 set() & copyWith() for

    Date & Calendar !38 import  static  java.util.Calendar.DECEMBER   ! def  date  =  new  Date().clearTime()   date.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  yearLater  =  date.copyWith(year:  2014)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '25-­‐12-­‐2014' def  cal  =  Calendar.instance   cal.set(year:  2013,  month:  DECEMBER,  date:  25)   ! def  newCalendar  =  cal.copyWith(date:  15)   assert  newCalendar.format('dd-­‐MM-­‐yyyy')  ==  '15-­‐12-­‐2013' Mutate Clone and mutate
  88. @glaforge — Groovy Grails eXchange 2013 Loop between Date &

    Calendar date points !39 def  today  =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! today.upto(nextWeek)  {          println  it.format('dd  MMMM')   }
  89. @glaforge — Groovy Grails eXchange 2013 Loop between Date &

    Calendar date points !39 def  today  =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! today.upto(nextWeek)  {          println  it.format('dd  MMMM')   } Iterate between dates with upto() and downto()
  90. @glaforge — Groovy Grails eXchange 2013 Loop between Date &

    Calendar date points !39 def  today  =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! today.upto(nextWeek)  {          println  it.format('dd  MMMM')   } def  to  =  Calendar.instance   to.set(year:  2013,  month:  Calendar.DECEMBER,  date:  10)   ! def  from  =  Calendar.instance   from.set(year:  2013,  month:  Calendar.DECEMBER,  date:  25)   ! from.downto(to)  {          println  it.format('dd  MMMM')   } Iterate between dates with upto() and downto()
  91. @glaforge — Groovy Grails eXchange 2013 Loop between Date &

    Calendar date points !39 def  today  =  new  Date().clearTime()   def  nextWeek  =  today  +  7   ! today.upto(nextWeek)  {          println  it.format('dd  MMMM')   } def  to  =  Calendar.instance   to.set(year:  2013,  month:  Calendar.DECEMBER,  date:  10)   ! def  from  =  Calendar.instance   from.set(year:  2013,  month:  Calendar.DECEMBER,  date:  25)   ! from.downto(to)  {          println  it.format('dd  MMMM')   } Iterate between dates with upto() and downto() upto() and downto() work with Calendars too
  92. Miscellaneous Groovysh improvements @Grab resolved against 
 Bintray JCenter

  93. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — doc

    command !41
  94. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — doc

    command !41 Launches your browser with the JavaDoc and GDK doc of the class
  95. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — completion

    !42
  96. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — completion

    !42 Import completion
  97. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — completion

    !42 Import completion Method call completion
  98. @glaforge — Groovy Grails eXchange 2013 Bintray JCenter repository •

    JFrog’s Bintray JCenter first in 
 the resolver chain for your @Grab statements ! – faster and more responsive 
 than Maven Central – always proper dependencies with checksums – stores and caches dependencies coming from Maven Central if not initially available !43
  99. Groovy 2.3 Part 2

  100. @glaforge — Groovy Grails eXchange 2013 Traits !45

  101. @glaforge — Groovy Grails eXchange 2013 Traits !45 trait  FlyingAbility

     {          String  fly()  {                  "I  believe  I  can  fly!"          }   }
  102. @glaforge — Groovy Grails eXchange 2013 Traits !45 trait  FlyingAbility

     {          String  fly()  {                  "I  believe  I  can  fly!"          }   } A trait keyword applying the @Trait transformation
  103. @glaforge — Groovy Grails eXchange 2013 Traits !45 trait  FlyingAbility

     {          String  fly()  {                  "I  believe  I  can  fly!"          }   } A trait keyword applying the @Trait transformation class  Car  implements  FlyingAbility  {} A class « implements » the trait def  c  =  new  Car()   assert  c.fly()  ==  "I  believe  I  can  fly!"
  104. @glaforge — Groovy Grails eXchange 2013 Traits • But open

    questions remain: ! – Should traits be stateful or stateless? ! – Aren’t Java 8 interface default methods enough for traits? ! – What are the rules of precedence / shadowing when implementing 2 traits with methods of the same signature? ! – What is the best implementation approach?
 (delegation based, bytecode weaving, companion-class…) !46
  105. @glaforge — Groovy Grails eXchange 2013 Traits • But open

    questions remain: ! – Should traits be stateful or stateless? ! – Aren’t Java 8 interface default methods enough for traits? ! – What are the rules of precedence / shadowing when implementing 2 traits with methods of the same signature? ! – What is the best implementation approach?
 (delegation based, bytecode weaving, companion-class…) !46
  106. @glaforge — Groovy Grails eXchange 2013 Traits • But open

    questions remain: ! – Should traits be stateful or stateless? ! – Aren’t Java 8 interface default methods enough for traits? ! – What are the rules of precedence / shadowing when implementing 2 traits with methods of the same signature? ! – What is the best implementation approach?
 (delegation based, bytecode weaving, companion-class…) !46 0QVUVCVGHWN
  107. @glaforge — Groovy Grails eXchange 2013 Traits • But open

    questions remain: ! – Should traits be stateful or stateless? ! – Aren’t Java 8 interface default methods enough for traits? ! – What are the rules of precedence / shadowing when implementing 2 traits with methods of the same signature? ! – What is the best implementation approach?
 (delegation based, bytecode weaving, companion-class…) !46 0QVUVCVGHWN (KTUVYKPU
  108. @glaforge — Groovy Grails eXchange 2013 Traits • But open

    questions remain: ! – Should traits be stateful or stateless? ! – Aren’t Java 8 interface default methods enough for traits? ! – What are the rules of precedence / shadowing when implementing 2 traits with methods of the same signature? ! – What is the best implementation approach?
 (delegation based, bytecode weaving, companion-class…) !46 0QVUVCVGHWN (KTUVYKPU
  109. @glaforge — Groovy Grails eXchange 2013 @TailRecursive transformation !47

  110. @glaforge — Groovy Grails eXchange 2013 @TailRecursive transformation !47 @groovy.transform.TailRecursive

      def  fact(n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }
  111. @glaforge — Groovy Grails eXchange 2013 @TailRecursive transformation !47 @groovy.transform.TailRecursive

      def  fact(n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   } https://github.com/jlink/tailrec
  112. @glaforge — Groovy Grails eXchange 2013 @TailRecursive transformation !47 @groovy.transform.TailRecursive

      def  fact(n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   } https://github.com/jlink/tailrec Transformation applied to methods, not closures
  113. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   }
  114. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } atomic  {  println  "hi"  }
  115. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } interface  ParameterizedAction  {          void  execute(int  i)   }   ! void  atomic(ParameterizedAction  pa)  {          pa.execute(1)   } atomic  {  println  "hi"  }
  116. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } interface  ParameterizedAction  {          void  execute(int  i)   }   ! void  atomic(ParameterizedAction  pa)  {          pa.execute(1)   } atomic  {  println  "hi"  } We’d get an ambiguous method exception
  117. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } interface  ParameterizedAction  {          void  execute(int  i)   }   ! void  atomic(ParameterizedAction  pa)  {          pa.execute(1)   } atomic  {  println  "hi"  } atomic  {  int  i  -­‐>  println  "hi  $i"  } We’d get an ambiguous method exception
  118. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } interface  ParameterizedAction  {          void  execute(int  i)   }   ! void  atomic(ParameterizedAction  pa)  {          pa.execute(1)   } atomic  {  println  "hi"  } atomic  {  int  i  -­‐>  println  "hi  $i"  } We’d get an ambiguous method exception Finer grained coercion to distinguish correct coercion depending on closure’s arguments
  119. @glaforge — Groovy Grails eXchange 2013 New website and documentation

    • New reference documentation and
 guides, using AsciiDoctor ! • New website with a 
 refreshed skin and the 
 new content !49
  120. @glaforge — Groovy Grails eXchange 2013 New website and documentation

    • New reference documentation and
 guides, using AsciiDoctor ! • New website with a 
 refreshed skin and the 
 new content !49 Looking for contributions!
  121. @glaforge — Groovy Grails eXchange 2013 GroovyDoc template overhaul !50

  122. @glaforge — Groovy Grails eXchange 2013 GroovyDoc template overhaul !50

    GroovyDoc != Sexy Doc
  123. @glaforge — Groovy Grails eXchange 2013 GroovyDoc template overhaul !50

    GroovyDoc != Sexy Doc Looking for contributions!
  124. Groovy 3.0 Part 3

  125. None
  126. MOP 2 New Age Meta-Object Protocol

  127. @glaforge — Groovy Grails eXchange 2013 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? !54
  128. Antlr v4 Grammar Rewriting the Groovy grammar with Antlr v4

  129. @glaforge — Groovy Grails eXchange 2013 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 – Easier to 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! !56
  130. Java 8 support Support the new Java 8 features

  131. @glaforge — Groovy Grails eXchange 2013 Java 8 support •

    Additional grammar and semantics features to support – to keep saying Groovy / Java interop is awesome! ! • New in Java 8 – lambdas – method references – default methods in interfaces – stream API, date / time API – annotations on types & repeated annotations !58
  132. Summary

  133. None
  134. None
  135. Rocks the JVM since 2003

  136. Thanks for your attention!

  137. Q & A