What’s new inGroovy 2.0? Guillaume Laforge  Groovy Project Manager  SpringSource / VMware     @glaforge
Guillaume Laforge • Groovy Project Manager at VMware  •   Initiator of the Grails framework  •   Creator of the Gaelyk • C...
Agenda (1/2) • What’s in Groovy 1.8?  •   Nicer DSLs with command chains  •   Runtime performance improvements  •   GPars ...
Agenda (2/2) • What’s new in Groovy 2.0?  •   Alignments with JDK 7      •Project Coin (small language changes)      •Invo...
Command chains • A grammar improvement allowing you   to drop dots & parens when chaining method calls  •   an extended ve...
Command chains          pull	  request	  	  on	  github	  
Command chains             Alternation of             method names          pull	  request	  	  on	  github	  
Command chains             Alternation of             method names          pull	  request	  	  on	  github	              ...
Command chains          pull	  request	  	  on	  github	  
Command chains          Equivalent to:          	  	  	  	  (	  	  	  	  	  	  	  ).	  	  (	  	  	  	  	  	  )          pu...
Command chains
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
Command chains      //	  methods	  with	  multiple	  arguments	  (commas)      take	  coffee	  	  with	  sugar,	  milk	  	...
GPars bundled • GPars is bundled in the Groovy distribution • GPars covers a wide range of parallel   and concurrent parad...
Closure enhancements • Closure annotation parameters • Some more functional flavor  •   composition      • compose several ...
Closure annotation parameters       @Retention(RetentionPolicy.RUNTIME)       @interface	  Invariant	  {	  	  	  	        ...
Closure annotation parameters       @Retention(RetentionPolicy.RUNTIME)       @interface	  Invariant	  {	  	  	  	        ...
Closure memoization
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Closure memoization         def	  plus	  =	  {	  a,	  b	  -­‐>	  sleep	  1000;	  a	  +	  b	  }.memoize()         assert	  ...
Builtin JSON support • Consuming • Producing • Pretty-printing
Builtin JSON support    import	  groovy.json.*	      def	  payload	  =	  new	  URL(    	  	  	  	  "http://github.../json/...
Builtin JSON support  import	  groovy.json.*	    	    def	  json	  =	  new	  JsonBuilder()	    	    json.person	  {	  	  	...
Builtin JSON support  import	  groovy.json.*	    	    def	  json	  =	  new	  JsonBuilder()	    	                          ...
Builtin JSON support  import	  groovy.json.*	    	    println	  JsonOutput.prettyPrint(  	  	  	  {"person":{"name":"Guill...
New AST transformations •       @Log                  •       Controlling execution                                   •   ...
@Log • Four different loggers can be injected  •   @Log                        import	  groovy.util.logging.*	    •   @Com...
@Log • Four different loggers can be injected  •   @Log                        import	  groovy.util.logging.*	    •   @Com...
Controlling code execution  • Your application may run user’s code   •   what if the code runs in infinite loops or for too...
@ThreadInterrupt       @ThreadInterrupt       import	  groovy.transform.ThreadInterrupt	         	         while	  (true)	...
@ThreadInterrupt        @ThreadInterrupt        import	  groovy.transform.ThreadInterrupt	          	          while	  (tr...
@ToString • Provides a default     toString() method   import	  groovy.transform.ToString	                           	    ...
@EqualsAndHashCode • Provides default   import	  groovy.transform.EqualsAndHashCode	     implementations    	             ...
@TupleConstructor • Provides a « classical »   import	  groovy.transform.TupleConstructor	       constructor with all     ...
@InheritConstructors • Classes like Exception are painful when extended,   as all the base constructors should be replicat...
@InheritConstructors • Classes like Exception are painful when extended,   as all the base constructors should be replicat...
Compilation customizers • Ability to apply some customization to the Groovy compilation   process • Three available custom...
Imports customizer       def	  configuration	  =	  new	  CompilerConfiguration()       	         def	  custo	  =	  new	  I...
Miscellaneous • Compilation customizers • Java 7 diamond operator • Slashy and dollar slashy strings • New GDK methods • (...
Groovy 2.0 bird’s eye viewA more            Java 7       Static Type                Project Coin   Checkingmodular        ...
Groovy 2.0 bird’s eye viewA moremodularGroovy
Groovy Modularity • Groovy’s « all » JAR weighs in at 6 MB • Nobody needs everything  •   Template engine, Ant scripting, ...
The new JARs • A smaller JAR: 3MB • Modules     –   console        –   jsr-223     –   test               –   docgenerator...
The new JARs • A smaller JAR: 3MB • Modules     –   console        –   jsr-223     –   test               –   docgenerator...
Extension modules • Create your own module  •   contribute instance extension methods       package	  foo       class	  St...
Extension modules • Create your own module                                                 Same structure                 ...
Extension modules • Create your own module  •   contribute class extension methods                    package	  foo       ...
Extension module descriptor • Descriptor in: META-INF/services/   org.codehaus.groovy.runtime.ExtensionModule     moduleNa...
Groovy 2.0 bird’s eye viewA more            Java 7       Static Type                Project Coin   Checkingmodular        ...
Groovy 2.0 bird’s eye view                  Java 7                Project Coin                  Invoke                 Dyn...
Binary literals  • We had decimal, octal and hexadecimal      notations for number literals  •   We can now use binary    ...
Underscore in literals  • Now we can also add underscores    in number literals for more readability       long	  creditCa...
Multicatch  • One block for multiple exception caught   •   rather than duplicating the block        try	  {        	  	  ...
InvokeDynamic • Groovy 2.0 supports JDK 7’s invokeDynamic  •   compiler has a flag for compiling against JDK 7  •   might u...
Groovy 2.0 bird’s eye viewA more            Java 7       Static Type                Project Coin   Checkingmodular        ...
Groovy 2.0 bird’s eye view                             Static Type                             Checking                   ...
Static Type Checking  • Goal: make the Groovy compiler « grumpy »!   •   and throw compilation errors (not at runtime)  • ...
Typos in a variable or method               import	  groovy.transform.TypeChecked               	                 void	  m...
Typos in a variable or method               import	  groovy.transform.TypeChecked               	                 void	  m...
Typos in a variable or methodAnnotation can be at     import	  groovy.transform.TypeChecked                         	   cl...
Wrong assignments      //	  cannot	  assign	  value	  of	  type...	  to	  variable...      int	  x	  =	  new	  Object()   ...
Wrong assignments      //	  cannot	  assign	  value	  of	  type...	  to	  variable...      int	  x	  =	  new	  Object()   ...
Wrong return types       //	  checks	  if/else	  branch	  return	  values       @TypeChecked       int	  method()	  {     ...
Wrong return types       //	  checks	  if/else	  branch	  return	  values       @TypeChecked       int	  method()	  {     ...
Type inference        @TypeChecked	  test()	  {        	  	  	  	  def	  name	  =	  "	  	  Guillaume	  	  "        	      ...
Statically checked & dynamic methods           @TypeChecked           String	  greeting(String	  name)	  {           	  	 ...
Instanceof checks     @TypeChecked	       void	  test(Object	  val)	  {     	  	  	  	  if	  (val	  instanceof	  String)	 ...
Instanceof checks     @TypeChecked	       void	  test(Object	  val)	  {     	  	  	  	  if	  (val	  instanceof	  String)	 ...
Instanceof checks     @TypeChecked	       void	  test(Object	  val)	  {     	  	  	  	  if	  (val	  instanceof	  String)	 ...
Lowest Upper Bound • Represents the lowest « super » type classes have in common  •   may be virtual (aka « non-denotable ...
Lowest Upper Bound • Represents the lowest « super » type classes have in common  •   may be virtual (aka « non-denotable ...
Lowest Upper Bound • Represents the lowest « super » type classes have in common  •   may be virtual (aka « non-denotable ...
Flow typing • Static type checking shouldn’t complain even for bad coding   practicies which work without type checks    @...
Gotcha: static checking vs dynamic  • Type checking works at compile-time   •   adding @TypeChecked doesn’t change behavio...
Gotcha: runtime metaprogramming      @TypeChecked	        void	  test()	  {      	  	  	  	  Integer.metaClass.foo	  =	  {...
Gotcha: runtime metaprogramming      @TypeChecked	        void	  test()	  {      	  	  	  	  Integer.metaClass.foo	  =	  {...
Gotcha: runtime metaprogramming      @TypeChecked	        void	  test()	  {      	  	  	  	  Integer.metaClass.foo	  =	  {...
Gotcha: explicit type for closures   @TypeChecked	  test()	  {   	  	  	  	  ["a",	  "b",	  "c"].collect	  {   	  	  	  	 ...
Gotcha: explicit type for closures   @TypeChecked	  test()	  {   	  	  	  	  ["a",	  "b",	  "c"].collect	  {	  String	  it...
Closure shared variables           @TypeChecked	  test()	  {           	  	  	  	  def	  var	  =	  "abc"	  	  	  	  	  	  ...
Closure shared variables                                                              var assigned in the closure:        ...
Closure shared variables                                                                    var assigned in the closure:  ...
Closure shared variables                                                                     var assigned in the closure: ...
Closure shared variables       class	  A	  	  	  	  	  	  	  	  	  	  	  {	  void	  foo()	  {}	  }       class	  B	  exten...
Closure shared variables       class	  A	  	  	  	  	  	  	  	  	  	  	  {	  void	  foo()	  {}	  }       class	  B	  exten...
Static Compilation  • Given your Groovy code can be type checked...    we can as well compile it « statically »   •   ie. ...
Static Compilation: advantages • You gain:  • Type safety   • thanks to static type checking    • static compilation build...
Static Compilation: disadvantages  • But you loose:   •   Dynamic features       •metaclass changes, categories, etc.   • ...
Statically compiled & dynamic methods        @CompileStatic        String	  greeting(String	  name)	  {                   ...
What about performance? • Comparisons between:  •   Java  •   Groovy static compilation (Groovy 2.0)  •   Groovy with prim...
What about performance?                                                Pi (π)     Binary                                  ...
Summary: Groovy 2.0 themes • Modularity • Embark the JDK 7 enhancements  • Project Coin  • Invoke Dynamic • Static aspects...
Thank you!                                  ge                           e Lafor lopment             Gu illaum ovy Deve   ...
Q&A
Roadmap • Groovy 2.1 — end of year            • Groovy 3.0 — 2013  •   @DelegatesTo annotation, for      •   new Meta-Obje...
Upcoming SlideShare
Loading in...5
×

Groovy 2.0 update at Devoxx 2012

1,447

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,447
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
27
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Groovy 2.0 update at Devoxx 2012

  1. 1. What’s new inGroovy 2.0? Guillaume Laforge Groovy Project Manager SpringSource / VMware @glaforge
  2. 2. Guillaume Laforge • Groovy Project Manager at VMware • Initiator of the Grails framework • Creator of the Gaelyk • Co-author of Groovy in Action • Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge
  3. 3. Agenda (1/2) • What’s in Groovy 1.8? • Nicer DSLs with command chains • Runtime performance improvements • GPars bundled for taming your multicores • Closure enhancements • Builtin JSON support • New AST transformations
  4. 4. Agenda (2/2) • What’s new in Groovy 2.0? • Alignments with JDK 7 •Project Coin (small language changes) •Invoke Dynamic support • Continued runtime performance improvements • Static type checking • Static compilation • Modularity
  5. 5. Command chains • A grammar improvement allowing you to drop dots & parens when chaining method calls • an extended version of top-level statements like println • Less dots, less parens allow you to • write more readable business rules • in almost plain English sentences • (or any language, of course)
  6. 6. Command chains pull  request    on  github  
  7. 7. Command chains Alternation of method names pull  request    on  github  
  8. 8. Command chains Alternation of method names pull  request    on  github   and parameters (even named ones)
  9. 9. Command chains pull  request    on  github  
  10. 10. Command chains Equivalent to:        (              ).    (            ) pull  request    on  github  
  11. 11. Command chains
  12. 12. Command chains //  methods  with  multiple  arguments  (commas)
  13. 13. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor
  14. 14. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation
  15. 15. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good
  16. 16. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures
  17. 17. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {}
  18. 18. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens
  19. 19. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens select  all    unique()  from  names
  20. 20. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens select  all    unique()  from  names //  possible  with  an  odd  number  of  terms
  21. 21. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens select  all    unique()  from  names //  possible  with  an  odd  number  of  terms take  3    cookies
  22. 22. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor        (            ).        (                      ).      (            ) //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens select  all    unique()  from  names //  possible  with  an  odd  number  of  terms take  3    cookies
  23. 23. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor        (            ).        (                      ).      (            ) //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good          (                              ).            (        ) //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {} //  zero-­‐arg  methods  require  parens select  all    unique()  from  names //  possible  with  an  odd  number  of  terms take  3    cookies
  24. 24. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor        (            ).        (                      ).      (            ) //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good          (                              ).            (        ) //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {}          (    ).        (    ).        (    ) //  zero-­‐arg  methods  require  parens select  all    unique()  from  names //  possible  with  an  odd  number  of  terms take  3    cookies
  25. 25. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor        (            ).        (                      ).      (            ) //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good          (                              ).            (        ) //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {}          (    ).        (    ).        (    ) //  zero-­‐arg  methods  require  parens select  all    unique()  from  names            (      ).                .        (          ) //  possible  with  an  odd  number  of  terms take  3    cookies
  26. 26. Command chains //  methods  with  multiple  arguments  (commas) take  coffee    with  sugar,  milk    and  liquor        (            ).        (                      ).      (            ) //  leverage  named-­‐args  as  punctuation check  that:  margarita    tastes  good          (                              ).            (        ) //  closure  parameters  for  new  control  structures given  {}    when  {}    then  {}          (    ).        (    ).        (    ) //  zero-­‐arg  methods  require  parens select  all    unique()  from  names            (      ).                .        (          ) //  possible  with  an  odd  number  of  terms take  3    cookies        (  ).
  27. 27. GPars bundled • GPars is bundled in the Groovy distribution • GPars covers a wide range of parallel and concurrent paradigms • actors, fork/join, map/filter/reduce, dataflow, agents • parallel arrays, executors, STM, and more... • And you can use it from plain Java as well! • http://gpars.codehaus.org/
  28. 28. Closure enhancements • Closure annotation parameters • Some more functional flavor • composition • compose several closures into one single closure • trampoline • avoid stack overflow errors for recursive algorithms • memoization • remember the outcome of previous closure invocations • currying improvements
  29. 29. Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface  Invariant  {                Class  value()  //  a  closure  class }   { @Invariant({  number  >=  0  }) class  Distance  {                float  number                String  unit }     def  d  =  new  Distance(number:  10,  unit:  "meters")   def  anno  =  Distance.getAnnotation(Invariant) def  check  =  anno.value().newInstance(d,  d) assert  check(d)
  30. 30. Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface  Invariant  {                Class  value()  //  a  closure  class }   Contr acts { @Invariant({  number  >=  0  }) class  Distance  {                float  number         P oor-m an’s G        String  unit }     def  d  =  new  Distance(number:  10,  unit:  "meters")   def  anno  =  Distance.getAnnotation(Invariant) def  check  =  anno.value().newInstance(d,  d) assert  check(d)
  31. 31. Closure memoization
  32. 32. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize()
  33. 33. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms
  34. 34. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately
  35. 35. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms
  36. 36. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately    
  37. 37. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately      
  38. 38. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached
  39. 39. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)
  40. 40. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)  
  41. 41. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)   //  at  most  10  invocations  cached
  42. 42. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)   //  at  most  10  invocations  cached def  plusAtMost  =  {  ...  }.memoizeAtMost(10)  
  43. 43. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)   //  at  most  10  invocations  cached def  plusAtMost  =  {  ...  }.memoizeAtMost(10)   //  between  10  and  20  invocations  cached
  44. 44. Closure memoization def  plus  =  {  a,  b  -­‐>  sleep  1000;  a  +  b  }.memoize() assert  plus(1,  2)  ==  3  //  after  1000ms assert  plus(1,  2)  ==  3  //  return  immediately assert  plus(2,  2)  ==  4  //  after  1000ms assert  plus(2,  2)  ==  4  //  return  immediately       //  at  least  10  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeAtLeast(10)   //  at  most  10  invocations  cached def  plusAtMost  =  {  ...  }.memoizeAtMost(10)   //  between  10  and  20  invocations  cached def  plusAtLeast  =  {  ...  }.memoizeBetween(10,  20)
  45. 45. Builtin JSON support • Consuming • Producing • Pretty-printing
  46. 46. Builtin JSON support import  groovy.json.*   def  payload  =  new  URL(        "http://github.../json/commits/...").text   def  slurper  =  new  JsonSlurper() def  doc  =  slurper.parseText(payload)   doc.commits.message.each  {  println  it  }
  47. 47. Builtin JSON support import  groovy.json.*     def  json  =  new  JsonBuilder()     json.person  {                name  "Guillaume"        age  35                pets  "Hector",  "Felix" }   println  json.toString()
  48. 48. Builtin JSON support import  groovy.json.*     def  json  =  new  JsonBuilder()     {                "person":  {                 json.person  {                        "name":  "Guillaume",                  name  "Guillaume"                "age":  35,                        age  35                        "pets":  [                                pets  "Hector",  "Felix"                        "Hector",                         }                          "Felix"                                ]         println  json.toString()        } }
  49. 49. Builtin JSON support import  groovy.json.*     println  JsonOutput.prettyPrint(      {"person":{"name":"Guillaume","age":35,"pets":["Hector","Felix"]}}) {                "person":  {                                "name":  "Guillaume",                      "age":  35,                                "pets":  [                                                "Hector",                                            "Felix"                                ]                } }
  50. 50. New AST transformations • @Log • Controlling execution • @ThreadInterrupt • @Field • @TimedInterrupt • @ConditionalInterrupt • @AutoClone • @InheritConstructor • @AutoExternalizable • @WithReadLock • @Canonical • @WithWriteLock • @ToString • @EqualsAndHashCode • @TupleConstructor • @ListenerList
  51. 51. @Log • Four different loggers can be injected • @Log import  groovy.util.logging.*   • @Commons   • @Log4j @Log class  Car  {         • @Slf4j        Car()  {                                log.info  Car  constructed                } • Possible to implement }     your own strategy def  c  =  new  Car()
  52. 52. @Log • Four different loggers can be injected • @Log import  groovy.util.logging.*   • @Commons   • @Log4j Guarded @Log class  Car  {         • @Slf4j w/ an if        Car()  {                                log.info  Car  constructed                } • Possible to implement }     your own strategy def  c  =  new  Car()
  53. 53. Controlling code execution • Your application may run user’s code • what if the code runs in infinite loops or for too long? • what if the code consumes too many resources? • 3 new transforms at your rescue • @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted • @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected • @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code
  54. 54. @ThreadInterrupt @ThreadInterrupt import  groovy.transform.ThreadInterrupt     while  (true)  {        //  eat  lots  of  CPU }
  55. 55. @ThreadInterrupt @ThreadInterrupt import  groovy.transform.ThreadInterrupt     while  (true)  { {        if  (Thread.currentThread().isInterrupted())                throw  new  InterruptedException()        //  eat  lots  of  CPU }
  56. 56. @ToString • Provides a default toString() method import  groovy.transform.ToString     to your types @ToString • Available options class  Person  {         • includeNames,        String  name                int  age includeFields, }   includeSuper,   excludes println  new  Person(name:  Pete,  age:  15) //  =>  Person(Pete,  15)
  57. 57. @EqualsAndHashCode • Provides default import  groovy.transform.EqualsAndHashCode   implementations   @EqualsAndHashCode for equals() class  Coord  {         and hashCode()        int  x,  y methods }     def  c1  =  new  Coord(x:  20,  y:  5) def  c2  =  new  Coord(x:  20,  y:  5)     assert  c1  ==  c2 assert  c1.hashCode()  ==  c2.hashCode()
  58. 58. @TupleConstructor • Provides a « classical » import  groovy.transform.TupleConstructor   constructor with all   @TupleConstructor   properties class  Person  {         • Several annotation        String  name         parameter options        int  age }   available   def  m  =  new  Person(Marion,  4)               assert  m.name  ==  Marion assert  m.age    ==  4
  59. 59. @InheritConstructors • Classes like Exception are painful when extended, as all the base constructors should be replicated class  CustomException  extends  Exception  {        CustomException()                                                {  super()              }        CustomException(String  msg)                            {  super(msg)        }        CustomException(String  msg,  Throwable  t)  {  super(msg,  t)  }        CustomException(Throwable  t)                          {  super(t)            } }
  60. 60. @InheritConstructors • Classes like Exception are painful when extended, as all the base constructors should be replicated import  groovy.transform.* @InheritConstructors class  CustomException  extends  Exception  {        CustomException()                                                {  super()              }        CustomException(String  msg)                            {  super(msg)        }        CustomException(String  msg,  Throwable  t)  {  super(msg,  t)  }        CustomException(Throwable  t)                          {  super(t)            } }
  61. 61. Compilation customizers • Ability to apply some customization to the Groovy compilation process • Three available customizers • ImportCustomizer • ASTTransformationCustomizer • SecureASTCustomizer • But you can implement your own
  62. 62. Imports customizer def  configuration  =  new  CompilerConfiguration()   def  custo  =  new  ImportCustomizer() custo.addStaticStar(Math.name) configuration.addCompilationCustomizers(custo)     def  result  =  new  GroovyShell(configuration)                          //  import  static  java.lang.Math.*        .evaluate("  cos  PI/3  ")                            
  63. 63. Miscellaneous • Compilation customizers • Java 7 diamond operator • Slashy and dollar slashy strings • New GDK methods • (G)String to Enum coercion • Customizing the Groovysh prompt • Executing remote scripts
  64. 64. Groovy 2.0 bird’s eye viewA more Java 7 Static Type Project Coin Checkingmodular Invoke StaticGroovy Dynamic Compilation
  65. 65. Groovy 2.0 bird’s eye viewA moremodularGroovy
  66. 66. Groovy Modularity • Groovy’s « all » JAR weighs in at 6 MB • Nobody needs everything • Template engine, Ant scripting, Swing UI building... • Provide a smaller core • and several smaller JARs per feature • Provide hooks for setting up DGM methods, etc.
  67. 67. The new JARs • A smaller JAR: 3MB • Modules – console – jsr-223 – test – docgenerator – jmx – testng – groovydoc – sql – json – groovysh – swing – xml – ant – servlet – bsf – templates
  68. 68. The new JARs • A smaller JAR: 3MB • Modules – console – jsr-223 – test – docgenerator – jmx – testng – groovydoc – sql – json – groovysh – swing – xml – ant – servlet – bsf – templates
  69. 69. Extension modules • Create your own module • contribute instance extension methods package  foo class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        } } //  usage:  "Guillaume".introduces("Cédric")
  70. 70. Extension modules • Create your own module Same structure as Categories • contribute instance extension methods package  foo class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        } } //  usage:  "Guillaume".introduces("Cédric")
  71. 71. Extension modules • Create your own module • contribute class extension methods package  foo class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        } } //  usage:  String.hi()
  72. 72. Extension module descriptor • Descriptor in: META-INF/services/ org.codehaus.groovy.runtime.ExtensionModule moduleName  =  stringExtensions moduleVersion  =  1.0 //  comma-­‐separated  list  of  classes extensionClasses  =  foo.StringExtension //  comma-­‐separated  list  of  classes staticExtensionClasses  =  foo.StaticStringExtension
  73. 73. Groovy 2.0 bird’s eye viewA more Java 7 Static Type Project Coin Checkingmodular Invoke StaticGroovy Dynamic Compilation
  74. 74. Groovy 2.0 bird’s eye view Java 7 Project Coin Invoke Dynamic
  75. 75. Binary literals • We had decimal, octal and hexadecimal notations for number literals • We can now use binary int  x  =  0b10101111 representations too assert  x  ==  175   byte  aByte  =  0b00100001 assert  aByte  ==  33   int  anInt  =  0b1010000101000101 assert  anInt  ==  41285
  76. 76. Underscore in literals • Now we can also add underscores in number literals for more readability long  creditCardNumber  =  1234_5678_9012_3456L long  socialSecurityNumbers  =  999_99_9999L float  monetaryAmount  =  12_345_132.12 long  hexBytes  =  0xFF_EC_DE_5E long  hexWords  =  0xFFEC_DE5E long  maxLong  =  0x7fff_ffff_ffff_ffffL long  alsoMaxLong  =  9_223_372_036_854_775_807L long  bytes  =  0b11010010_01101001_10010100_10010010
  77. 77. Multicatch • One block for multiple exception caught • rather than duplicating the block try  {        /*  ...  */ }  catch(IOException  |  NullPointerException  e)  {        /*  one  block  to  treat  2  exceptions  */ }
  78. 78. InvokeDynamic • Groovy 2.0 supports JDK 7’s invokeDynamic • compiler has a flag for compiling against JDK 7 • might use the invokeDynamic backport for < JDK 7 • Benefits • more runtime performance! • at least as fast as current « dynamic » Groovy • in the long run, will allow us to get rid of code! • call site caching, thanks to MethodHandles • metaclass registry, thanks to ClassValues • will let the JIT inline calls more easily
  79. 79. Groovy 2.0 bird’s eye viewA more Java 7 Static Type Project Coin Checkingmodular Invoke StaticGroovy Dynamic Compilation
  80. 80. Groovy 2.0 bird’s eye view Static Type Checking Static Compilation
  81. 81. Static Type Checking • Goal: make the Groovy compiler « grumpy »! • and throw compilation errors (not at runtime) • Not everybody needs dynamic features all the time • think Java libraries scripting • Grumpy should... • tell you about your method or variable typos • complain if you call methods that don’t exist • shout on assignments of wrong types • infer the types of your variables • figure out GDK methods
  82. 82. Typos in a variable or method import  groovy.transform.TypeChecked   void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme }
  83. 83. Typos in a variable or method import  groovy.transform.TypeChecked   void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"Compilation        //  variable  naamme  is  undeclared errors!        println  naamme }
  84. 84. Typos in a variable or methodAnnotation can be at import  groovy.transform.TypeChecked   class or method level void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"Compilation        //  variable  naamme  is  undeclared errors!        println  naamme }
  85. 85. Wrong assignments //  cannot  assign  value  of  type...  to  variable... int  x  =  new  Object() Set  set  =  new  Object()   def  o  =  new  Object() int  x  =  o   String[]  strings  =  [a,b,c] int  str  =  strings[0]   //  cannot  find  matching  method  plus() int  i  =  0 i  +=  1
  86. 86. Wrong assignments //  cannot  assign  value  of  type...  to  variable... int  x  =  new  Object() Set  set  =  new  Object() Compilation   def  o  =  new  Object() errors! int  x  =  o   String[]  strings  =  [a,b,c] int  str  =  strings[0]   //  cannot  find  matching  method  plus() int  i  =  0 i  +=  1
  87. 87. Wrong return types //  checks  if/else  branch  return  values @TypeChecked int  method()  {        if  (true)  {  String  }        else  {  42  } } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name }
  88. 88. Wrong return types //  checks  if/else  branch  return  values @TypeChecked int  method()  { Compilation        if  (true)  {  String  }        else  {  42  } error! } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name }
  89. 89. Type inference @TypeChecked  test()  {        def  name  =  "    Guillaume    "          //  String  type  infered  (even  inside  GString)        println  "NAME  =  ${name.toUpperCase()}"            //  Groovy  GDK  method  support        //  (GDK  operator  overloading  too)        println  name.trim()          int[]  numbers  =  [1,  2,  3]        //  Element  n  is  an  int        for  (int  n  in  numbers)  {                println  n        } }
  90. 90. Statically checked & dynamic methods @TypeChecked String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() }
  91. 91. Instanceof checks @TypeChecked   void  test(Object  val)  {        if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
  92. 92. Instanceof checks @TypeChecked   void  test(Object  val)  {        if  (val  instanceof  String)  { No need                println  val.toUpperCase() for casts        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
  93. 93. Instanceof checks @TypeChecked   void  test(Object  val)  {        if  (val  instanceof  String)  { No need                println  val.toUpperCase() for casts        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } } Can call String#multiply(int) from the Groovy Development Kit
  94. 94. Lowest Upper Bound • Represents the lowest « super » type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] }
  95. 95. Lowest Upper Bound • Represents the lowest « super » type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] } Inferred return type: List<Number & Comparable>
  96. 96. Lowest Upper Bound • Represents the lowest « super » type classes have in common • may be virtual (aka « non-denotable ») @TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14] } Inferred return type: List<Number & Comparable>
  97. 97. Flow typing • Static type checking shouldn’t complain even for bad coding practicies which work without type checks @TypeChecked  test()  {        def  var  =  123                  //  inferred  type  is  int        int  x  =  var                      //  var  is  an  int        var  =  "123"                      //  assign  var  with  a  String        x  =  var.toInteger()      //  no  problem,  no  need  to  cast        var  =  123        x  =  var.toUpperCase()  //  error,  var  is  int! }
  98. 98. Gotcha: static checking vs dynamic • Type checking works at compile-time • adding @TypeChecked doesn’t change behavior •do not confuse with static compilation • Most dynamic features cannot be type checked • metaclass changes, categories • dynamically bound variables (ex: script’s binding) • However, compile-time metaprogramming works • as long as proper type information is defined
  99. 99. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() }
  100. 100. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Not allowed: metaClass property is dynamic
  101. 101. Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Method not Not allowed: recognized metaClass property is dynamic
  102. 102. Gotcha: explicit type for closures @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Not  OK        } }
  103. 103. Gotcha: explicit type for closures @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  it’s  a  String        } }
  104. 104. Closure shared variables @TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! }
  105. 105. Closure shared variables var assigned in the closure: « shared closure variable » @TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! }
  106. 106. Closure shared variables var assigned in the closure: « shared closure variable » Impossible to @TypeChecked  test()  {        def  var  =  "abc"               ensure the        def  cl  =  {  var  =  new  Date()  } assignment        if  (random)  cl()really happens        var.toUpperCase()    //  Not  OK! }
  107. 107. Closure shared variables var assigned in the closure: « shared closure variable » Impossible to @TypeChecked  test()  {        def  var  =  "abc"               ensure the        def  cl  =  {  var  =  new  Date()  } assignment        if  (random)  cl()really happens        var.toUpperCase()    //  Not  OK! } Only methods of the most specific compatible type (LUB) are allowed by the type checker
  108. 108. Closure shared variables class  A                      {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        cl()        var.foo()      //  OK! }
  109. 109. Closure shared variables class  A                      {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        cl()        var.foo()      //  OK! } var is at least an instance of A
  110. 110. Static Compilation • Given your Groovy code can be type checked... we can as well compile it « statically » • ie. generate the same byte code as javac • Also interesting for those stuck in JDK < 7 to benefit from performance improvements
  111. 111. Static Compilation: advantages • You gain: • Type safety • thanks to static type checking • static compilation builds upon static type checking • Faster code • as close as possible to Java’s performance • Code immune to « monkey patching » • metaprogramming badly used can interfere with framework code • Smaller bytecode size
  112. 112. Static Compilation: disadvantages • But you loose: • Dynamic features •metaclass changes, categories, etc. • Dynamic method dispatch •although as close as possible to « dynamic » Groovy
  113. 113. Statically compiled & dynamic methods @CompileStatic String  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase()) }   //  usual  dynamic  behavior String  generateMarkup(String  name)  {        def  sw  =  new  StringWriter()        new  MarkupBuilder(sw).html  {                body  {                        div  name                }        }        sw.toString() }
  114. 114. What about performance? • Comparisons between: • Java • Groovy static compilation (Groovy 2.0) • Groovy with primitive optimizations (Groovy 1.8+) • Groovy without optimizations (Groovy 1.7)
  115. 115. What about performance? Pi (π) Binary Fibonacci quadrature trees Java 191 ms 97 ms 3.6 s Static 1.7 1.8 2.0 compilation 197 ms 101 ms 4.3 s Primitive optimizations 360 ms 111 ms 23.7 s No prim. optimizations 2590 ms 3220 ms 50.0 s
  116. 116. Summary: Groovy 2.0 themes • Modularity • Embark the JDK 7 enhancements • Project Coin • Invoke Dynamic • Static aspects • Static type checking • Static compilation
  117. 117. Thank you! ge e Lafor lopment Gu illaum ovy Deve Gro H ead of om ge@ gmail.c : glafor forge Email @gla orge : .to/glaf om Twitter : http://gplus spot.c + pp Google p://glaforge.a tt Blog: h
  118. 118. Q&A
  119. 119. Roadmap • Groovy 2.1 — end of year • Groovy 3.0 — 2013 • @DelegatesTo annotation, for • new Meta-Object Protocol better tooling & type checking • Java 8 lambda support • complete the invoke dynamic support • custom type checking for your • Groovy 4.0 — 2014 Domain-Specific Languages • meta-annotations for • moving to Antlr 4 combining AST • rewrite of the grammar transformations
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×