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

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

Guillaume Laforge

December 12, 2013
Tweet

More Decks by Guillaume Laforge

Other Decks in Technology

Transcript

  1. @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  }
  2. @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
  3. @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?
  4. @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
  5. @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
  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  } (it)  -­‐>  it  >  2 « Functional » interface Works with single abstract method classes too A bit verbose? Implicit closure coercion
  7. @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)
  8. @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
  9. @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
  10. @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)
  11. @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!
  12. @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
  13. @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) … … …
  14. @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) … … …
  15. @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) … … …
  16. @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) … … …
  17. @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) … … …
  18. @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) … … …
  19. @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) … … …
  20. @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)
  21. @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!
  22. @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) … … …
  23. @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) … … …
  24. @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) … … …
  25. @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) … … …
  26. @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 … … …
  27. @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!"          }   }
  28. @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
  29. @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…
  30. @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)
  31. @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
  32. @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
  33. @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
  34. @glaforge — Groovy Grails eXchange 2013 Annotation-driven base script class

    definition !25 import  groovy.transform.BaseScript   ! abstract  class  DeclaredBaseScript  extends  Script  {          int  meaningOfLife  =  42   }
  35. @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
  36. @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
  37. @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
  38. @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"          }   }
  39. @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
  40. @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
  41. @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?
  42. @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"
  43. @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
  44. @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
  45. @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
  46. @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
  47. @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!
  48. @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'          }   }
  49. @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
  50. @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
  51. @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
  52. @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()  {          //  ...   }
  53. @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
  54. @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!
  55. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

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

    new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   } incompatibleReturnType event
  57. @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
  58. @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)
  59. @glaforge — Groovy Grails eXchange 2013 Type checking extensions —

    new events !32 ambiguousMethods  {  methods,  origin  -­‐>          methods.find  {  it.parameters.any  {                    it.type  ==  classNodeFor(Integer)  }            }   }
  60. @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
  61. @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
  62. @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)   }
  63. @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
  64. @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!
  65. @glaforge — Groovy Grails eXchange 2013 Remove part of strings

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

    with a regex !35 assert  ('Hello  Groovy  world!'  -­‐  ~/\s+Gr\w+/)                            ==  'Hello  world!' A String
  67. @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
  68. @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!
  69. @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          }   }
  70. @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]]
  71. @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
  72. @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',  '[email protected]')   ! def  jdGmail  =  jdEx.copyWith(email:  '[email protected]')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  '[email protected]'   }
  73. @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',  '[email protected]')   ! def  jdGmail  =  jdEx.copyWith(email:  '[email protected]')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  '[email protected]'   } Specify you want the copyWith() method
  74. @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',  '[email protected]')   ! def  jdGmail  =  jdEx.copyWith(email:  '[email protected]')   ! jdGmail.with  {          assert  name  ==  'John  Doe'          assert  email  ==  '[email protected]'   } Specify you want the copyWith() method New immutable user with a different email
  75. @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'
  76. @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
  77. @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
  78. @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
  79. @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')   }
  80. @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()
  81. @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()
  82. @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
  83. @glaforge — Groovy Grails eXchange 2013 Groovysh enhancements — doc

    command !41 Launches your browser with the JavaDoc and GDK doc of the class
  84. @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
  85. @glaforge — Groovy Grails eXchange 2013 Traits !45 trait  FlyingAbility

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

     {          String  fly()  {                  "I  believe  I  can  fly!"          }   } A trait keyword applying the @Trait transformation
  87. @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!"
  88. @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
  89. @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
  90. @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
  91. @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
  92. @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
  93. @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)   }
  94. @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
  95. @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
  96. @glaforge — Groovy Grails eXchange 2013 Finer-grained implicit closure coercion

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

    !48 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } atomic  {  println  "hi"  }
  98. @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"  }
  99. @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
  100. @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
  101. @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
  102. @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
  103. @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!
  104. @glaforge — Groovy Grails eXchange 2013 GroovyDoc template overhaul !50

    GroovyDoc != Sexy Doc Looking for contributions!
  105. @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
  106. @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
  107. @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