Slide 1

Slide 1 text

Guillaume Laforge 
 @glaforge Groovy in 2014 and beyond

Slide 2

Slide 2 text

Guillaume  Laforge Groovy project lead at . ! @glaforge http://glaforge.appspot.com

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Groovy 2.2 Part 1

Slide 5

Slide 5 text

Implicit closure coercion Java 8 style :-)

Slide 6

Slide 6 text

@glaforge — Greach 2014 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  }

Slide 7

Slide 7 text

@glaforge — Greach 2014 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

Slide 8

Slide 8 text

@glaforge — Greach 2014 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?

Slide 9

Slide 9 text

@glaforge — Greach 2014 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

Slide 10

Slide 10 text

@glaforge — Greach 2014 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

Slide 11

Slide 11 text

@glaforge — Greach 2014 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

Slide 12

Slide 12 text

AST transforms @Memoized @Log4j2

Slide 13

Slide 13 text

@glaforge — Greach 2014 @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)

Slide 14

Slide 14 text

@glaforge — Greach 2014 @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

Slide 15

Slide 15 text

@glaforge — Greach 2014 @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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

@glaforge — Greach 2014 @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!

Slide 18

Slide 18 text

@glaforge — Greach 2014 @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

Slide 19

Slide 19 text

@glaforge — Greach 2014 @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) … … …

Slide 20

Slide 20 text

@glaforge — Greach 2014 @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) … … …

Slide 21

Slide 21 text

@glaforge — Greach 2014 @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) … … …

Slide 22

Slide 22 text

@glaforge — Greach 2014 @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) … … …

Slide 23

Slide 23 text

@glaforge — Greach 2014 @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) … … …

Slide 24

Slide 24 text

@glaforge — Greach 2014 @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) … … …

Slide 25

Slide 25 text

@glaforge — Greach 2014 @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) … … …

Slide 26

Slide 26 text

@glaforge — Greach 2014 … … … @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)

Slide 27

Slide 27 text

@glaforge — Greach 2014 … … … @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!

Slide 28

Slide 28 text

@glaforge — Greach 2014 @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) … … …

Slide 29

Slide 29 text

@glaforge — Greach 2014 @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) … … …

Slide 30

Slide 30 text

@glaforge — Greach 2014 @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) … … …

Slide 31

Slide 31 text

@glaforge — Greach 2014 @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) … … …

Slide 32

Slide 32 text

@glaforge — Greach 2014 @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 … … …

Slide 33

Slide 33 text

@glaforge — Greach 2014 Log4j2 @Log variant !22 import  groovy.util.logging.Log4j2   ! @Log4j2   class  MyClass  {          void  doSomething()  {                  log.info  "did  something  groovy  today!"          }   }

Slide 34

Slide 34 text

@glaforge — Greach 2014 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

Slide 35

Slide 35 text

@glaforge — Greach 2014 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…

Slide 36

Slide 36 text

@glaforge — Greach 2014 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)

Slide 37

Slide 37 text

@glaforge — Greach 2014 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

Slide 38

Slide 38 text

@glaforge — Greach 2014 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

Slide 39

Slide 39 text

@glaforge — Greach 2014 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

Slide 40

Slide 40 text

Base script classes Delegation Annotation-driven base class DelegatingScript @DelegatesTo refinement

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

@glaforge — Greach 2014 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

Slide 44

Slide 44 text

@glaforge — Greach 2014 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

Slide 45

Slide 45 text

@glaforge — Greach 2014 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"          }   }

Slide 46

Slide 46 text

@glaforge — Greach 2014 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

Slide 47

Slide 47 text

@glaforge — Greach 2014 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

Slide 48

Slide 48 text

@glaforge — Greach 2014 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?

Slide 49

Slide 49 text

@glaforge — Greach 2014 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"

Slide 50

Slide 50 text

@glaforge — Greach 2014 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

Slide 51

Slide 51 text

@glaforge — Greach 2014 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

Slide 52

Slide 52 text

@glaforge — Greach 2014 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

Slide 53

Slide 53 text

@glaforge — Greach 2014 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

Slide 54

Slide 54 text

@glaforge — Greach 2014 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!

Slide 55

Slide 55 text

@glaforge — Greach 2014 @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  {}   ! public    Object  map(              @DelegatesTo.Target  List  target,              @DelegatesTo(genericTypeIndex  =  0)  Closure  arg)  {          arg.delegate  =  target.join('')          arg()   }   ! def  test()  {          map(new  MyList(['f',  'o',  'o']))  {                  assert  toUpperCase()  ==  'FOO'          }   }

Slide 56

Slide 56 text

@glaforge — Greach 2014 @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  {}   ! public    Object  map(              @DelegatesTo.Target  List  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

Slide 57

Slide 57 text

@glaforge — Greach 2014 @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  {}   ! public    Object  map(              @DelegatesTo.Target  List  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

Slide 58

Slide 58 text

@glaforge — Greach 2014 @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  {}   ! public    Object  map(              @DelegatesTo.Target  List  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

Slide 59

Slide 59 text

Type checking extensions Precompilation New events Dynamic calls

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

@glaforge — Greach 2014 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

Slide 62

Slide 62 text

@glaforge — Greach 2014 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!

Slide 63

Slide 63 text

@glaforge — Greach 2014 Type checking extensions — new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   }

Slide 64

Slide 64 text

@glaforge — Greach 2014 Type checking extensions — new events !31 incompatibleReturnType  {  returnStmt,  inferredReturnType  -­‐>          if  (inferredReturnType  ==  STRING_TYPE)  {                  handled  =  true          }   } incompatibleReturnType event

Slide 65

Slide 65 text

@glaforge — Greach 2014 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

Slide 66

Slide 66 text

@glaforge — Greach 2014 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)

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

@glaforge — Greach 2014 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

Slide 70

Slide 70 text

@glaforge — Greach 2014 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)   }

Slide 71

Slide 71 text

@glaforge — Greach 2014 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

Slide 72

Slide 72 text

@glaforge — Greach 2014 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!

Slide 73

Slide 73 text

GDK improvements MrHaki 
 approved!

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

@glaforge — Greach 2014 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!

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

@glaforge — Greach 2014 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]]

Slide 80

Slide 80 text

@glaforge — Greach 2014 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

Slide 81

Slide 81 text

@glaforge — Greach 2014 @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]'   }

Slide 82

Slide 82 text

@glaforge — Greach 2014 @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

Slide 83

Slide 83 text

@glaforge — Greach 2014 @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

Slide 84

Slide 84 text

@glaforge — Greach 2014 set() & copyWith() for Date & Calendar !38 import  static  java.util.Calendar.MARCH   ! def  date  =  new  Date().clearTime()   date.set(year:  2014,  month:  MARCH,  date:  28)   ! def  yearLater  =  date.copyWith(year:  2015)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '28-­‐03-­‐2015'

Slide 85

Slide 85 text

@glaforge — Greach 2014 set() & copyWith() for Date & Calendar !38 import  static  java.util.Calendar.MARCH   ! def  date  =  new  Date().clearTime()   date.set(year:  2014,  month:  MARCH,  date:  28)   ! def  yearLater  =  date.copyWith(year:  2015)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '28-­‐03-­‐2015' Mutate

Slide 86

Slide 86 text

@glaforge — Greach 2014 set() & copyWith() for Date & Calendar !38 import  static  java.util.Calendar.MARCH   ! def  date  =  new  Date().clearTime()   date.set(year:  2014,  month:  MARCH,  date:  28)   ! def  yearLater  =  date.copyWith(year:  2015)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '28-­‐03-­‐2015' def  cal  =  Calendar.instance   cal.set(year:  2014,  month:  MARCH,  date:  26)   ! def  newCalendar  =  cal.copyWith(date:  27)   assert  newCalendar.format('dd-­‐MM-­‐yyyy')  ==  '27-­‐03-­‐2014' Mutate

Slide 87

Slide 87 text

@glaforge — Greach 2014 set() & copyWith() for Date & Calendar !38 import  static  java.util.Calendar.MARCH   ! def  date  =  new  Date().clearTime()   date.set(year:  2014,  month:  MARCH,  date:  28)   ! def  yearLater  =  date.copyWith(year:  2015)   assert  yearLater.format('dd-­‐MM-­‐yyyy')  ==  '28-­‐03-­‐2015' def  cal  =  Calendar.instance   cal.set(year:  2014,  month:  MARCH,  date:  26)   ! def  newCalendar  =  cal.copyWith(date:  27)   assert  newCalendar.format('dd-­‐MM-­‐yyyy')  ==  '27-­‐03-­‐2014' Mutate Clone and mutate

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

@glaforge — Greach 2014 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()

Slide 90

Slide 90 text

@glaforge — Greach 2014 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:  2014,  month:  Calendar.MARCH,  date:  10)   ! def  from  =  Calendar.instance   from.set(year:  2014,  month:  Calendar.MARCH,  date:  28)   ! from.downto(to)  {          println  it.format('dd  MMMM')   } Iterate between dates with upto() and downto()

Slide 91

Slide 91 text

@glaforge — Greach 2014 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:  2014,  month:  Calendar.MARCH,  date:  10)   ! def  from  =  Calendar.instance   from.set(year:  2014,  month:  Calendar.MARCH,  date:  28)   ! from.downto(to)  {          println  it.format('dd  MMMM')   } Iterate between dates with upto() and downto() upto() and downto() work with Calendars too

Slide 92

Slide 92 text

Miscellaneous Groovysh improvements @Grab resolved against 
 Bintray JCenter

Slide 93

Slide 93 text

@glaforge — Greach 2014 Groovysh enhancements — doc command !41

Slide 94

Slide 94 text

@glaforge — Greach 2014 Groovysh enhancements — doc command !41 Launches your browser with the JavaDoc and GDK doc of the class

Slide 95

Slide 95 text

@glaforge — Greach 2014 Groovysh enhancements — completion !42

Slide 96

Slide 96 text

@glaforge — Greach 2014 Groovysh enhancements — completion !42 Import completion

Slide 97

Slide 97 text

@glaforge — Greach 2014 Groovysh enhancements — completion !42 Import completion Method call completion

Slide 98

Slide 98 text

@glaforge — Greach 2014 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

Slide 99

Slide 99 text

Groovy 2.3 Part 2

Slide 100

Slide 100 text

@glaforge — Greach 2014 Super fast JSON support! ! • New parsers and builders have been contributed – by Rick Hightower & Andrey Bloschetsov ! • Making Groovy serialization / deserialization faster than – GSON – Jackson !45

Slide 101

Slide 101 text

@glaforge — Greach 2014 A new template engine, markup based !46

Slide 102

Slide 102 text

@glaforge — Greach 2014 A new template engine, markup based !46 import  groovy.text.markup.*   ! MarkupTemplateEngine  engine  =  new  MarkupTemplateEngine(          new  TemplateConfiguration())   def  template  =  engine.createTemplate  '''          html  {                  head  {                          include  template:  'header.gtpl'                  }                  body  {                          p  "Hello  Greach"                  }          }   '''   System.out  <<  template.make()

Slide 103

Slide 103 text

@glaforge — Greach 2014 A new template engine, markup based !46 import  groovy.text.markup.*   ! MarkupTemplateEngine  engine  =  new  MarkupTemplateEngine(          new  TemplateConfiguration())   def  template  =  engine.createTemplate  '''          html  {                  head  {                          include  template:  'header.gtpl'                  }                  body  {                          p  "Hello  Greach"                  }          }   '''   System.out  <<  template.make() Type-checked models, bytecode-compiled templates, includes, custom indentation, (un)escaping, i18n support, and more

Slide 104

Slide 104 text

@glaforge — Greach 2014 Traits !47

Slide 105

Slide 105 text

@glaforge — Greach 2014 Traits !47 trait  FlyingAbility  {          String  fly()  {                  "I  believe  I  can  fly!"          }   }

Slide 106

Slide 106 text

@glaforge — Greach 2014 Traits !47 trait  FlyingAbility  {          String  fly()  {                  "I  believe  I  can  fly!"          }   } A trait keyword applying the @Trait transformation

Slide 107

Slide 107 text

@glaforge — Greach 2014 Traits !47 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!"

Slide 108

Slide 108 text

@glaforge — Greach 2014 Traits characteristics • Groovy traits are stateful – Java 8’s default methods won’t cut it here ! • Precedence: When implementing several traits, 
 first declared trait wins – in case both traits have a method with the same signature ! • Supports runtime mixing of traits with ‘as’ !48

Slide 109

Slide 109 text

@glaforge — Greach 2014 Stateful traits !49

Slide 110

Slide 110 text

@glaforge — Greach 2014 Stateful traits !49 trait  Named  {          String  name   }   ! class  Phone  implements  Named  {}   ! def  phone  =  new  Phone(name:  'Galaxy  S3')   assert  phone.name  ==  'Galaxy  S3'

Slide 111

Slide 111 text

@glaforge — Greach 2014 Stateful traits !49 trait  Named  {          String  name   }   ! class  Phone  implements  Named  {}   ! def  phone  =  new  Phone(name:  'Galaxy  S3')   assert  phone.name  ==  'Galaxy  S3' A usual Groovy property!

Slide 112

Slide 112 text

@glaforge — Greach 2014 Trait inheritance !50

Slide 113

Slide 113 text

@glaforge — Greach 2014 Trait inheritance !50 trait  Named  {          String  name   }   ! trait  NameSpeakable  implements  Named  {          String  speak()  {  "My  name  is  ${name}"  }   }   ! class  Phone  implements  NamedSpeakable  {}   ! def  phone  =  new  Phone(name:  'Galaxy  S3')   assert  phone.speak()  ==  'My  name  is  Galaxy  S3'

Slide 114

Slide 114 text

@glaforge — Greach 2014 Trait inheritance !50 trait  Named  {          String  name   }   ! trait  NameSpeakable  implements  Named  {          String  speak()  {  "My  name  is  ${name}"  }   }   ! class  Phone  implements  NamedSpeakable  {}   ! def  phone  =  new  Phone(name:  'Galaxy  S3')   assert  phone.speak()  ==  'My  name  is  Galaxy  S3' Implement the parent trait

Slide 115

Slide 115 text

@glaforge — Greach 2014 Runtime traits !51

Slide 116

Slide 116 text

@glaforge — Greach 2014 Runtime traits !51 trait  Flying  {          String  fly()  {  "I'm  flying!"  }   }   ! class  Duck  {}   def  d  =  new  Duck()  as  Flying   ! assert  d  instanceof  Flying   assert  d.fly()  ==  "I'm  flying!"

Slide 117

Slide 117 text

@glaforge — Greach 2014 Runtime traits !51 trait  Flying  {          String  fly()  {  "I'm  flying!"  }   }   ! class  Duck  {}   def  d  =  new  Duck()  as  Flying   ! assert  d  instanceof  Flying   assert  d.fly()  ==  "I'm  flying!" Implement Flying trait at runtime

Slide 118

Slide 118 text

@glaforge — Greach 2014 @TailRecursive transformation !52

Slide 119

Slide 119 text

@glaforge — Greach 2014 @TailRecursive transformation !52 @groovy.transform.TailRecursive   def  fact(n,  accu  =  1G)  {          if  (n  <  2)  accu          else  fact(n  -­‐  1,  n  *  accu)   }

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

@glaforge — Greach 2014 @TailRecursive transformation !52 @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

Slide 122

Slide 122 text

@glaforge — Greach 2014 New website and documentation • New reference documentation and
 guides, using AsciiDoctor ! • New website with a 
 refreshed skin and the 
 new content !53

Slide 123

Slide 123 text

@glaforge — Greach 2014 New website and documentation • New reference documentation and
 guides, using AsciiDoctor ! • New website with a 
 refreshed skin and the 
 new content !53 Looking for contributions!

Slide 124

Slide 124 text

@glaforge — Greach 2014 GroovyDoc template overhaul !54

Slide 125

Slide 125 text

@glaforge — Greach 2014 GroovyDoc template overhaul !54 GroovyDoc != Sexy Doc

Slide 126

Slide 126 text

@glaforge — Greach 2014 GroovyDoc template overhaul !54 GroovyDoc != Sexy Doc

Slide 127

Slide 127 text

@glaforge — Greach 2014 GroovyDoc template overhaul !54 GroovyDoc != Sexy Doc Would also be nice for Groovy GDK ocumentation

Slide 128

Slide 128 text

If users ask…

Slide 129

Slide 129 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   }

Slide 130

Slide 130 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 interface  Action  {          void  act()   }   ! void  atomic(Action  a)  {          a.act()   } atomic  {  println  "hi"  }

Slide 131

Slide 131 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 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"  }

Slide 132

Slide 132 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 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

Slide 133

Slide 133 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 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

Slide 134

Slide 134 text

@glaforge — Greach 2014 Finer-grained implicit closure coercion !56 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

Slide 135

Slide 135 text

Groovy 3.0 Part 3

Slide 136

Slide 136 text

No content

Slide 137

Slide 137 text

MOP 2 New Age Meta-Object Protocol

Slide 138

Slide 138 text

@glaforge — Greach 2014 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? !60

Slide 139

Slide 139 text

Antlr v4 Grammar Rewriting the Groovy grammar with Antlr v4

Slide 140

Slide 140 text

@glaforge — Greach 2014 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! !62

Slide 141

Slide 141 text

@glaforge — Greach 2014 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! !62

Slide 142

Slide 142 text

Java 8 support Support the new Java 8 features

Slide 143

Slide 143 text

@glaforge — Greach 2014 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 !64

Slide 144

Slide 144 text

Summary

Slide 145

Slide 145 text

No content

Slide 146

Slide 146 text

No content

Slide 147

Slide 147 text

Rocks the JVM since 2003

Slide 148

Slide 148 text

Thanks for your attention!

Slide 149

Slide 149 text

Q & A