• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Groovy 2 and beyond
 

Groovy 2 and beyond

on

  • 2,947 views

"Groovy 2.0 and beyond" presentation given at the Groovy/Grails eXchange conference.

"Groovy 2.0 and beyond" presentation given at the Groovy/Grails eXchange conference.

Video can be seen here:
http://skillsmatter.com/podcast/groovy-grails/keynote-speech

Statistics

Views

Total Views
2,947
Views on SlideShare
2,920
Embed Views
27

Actions

Likes
8
Downloads
51
Comments
0

3 Embeds 27

https://twitter.com 16
http://eventifier.co 9
http://translate.googleusercontent.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Groovy 2 and beyond Groovy 2 and beyond Presentation Transcript

    • Groovy 2.0and beyondGuillaume LaforgeGroovy Project ManagerSpringSource / VMware@glaforge
    • 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
    • A blossomingECOSYSTEM
    • GVM
    • GVM
    • GVMGROOVYENVIRONMENTMANAGER
    • GVM: Groovy enVironment Manager • New kid in town! • http://gvmtool.net/ — @gvmtool • Manage parallel versions of various SDKs • Currently supports • Groovy, Grails, Griffon, Gradle,Vert.x • On Linux, MacOS, Cygwin, Solaris, FreeBSD
    • GROOVY
    • Groovy 2.0 bird’s eye view Java 7 Static TypeA more Project Checkingmodular CoinGroovy Invoke Static Compilation Dynamic
    • 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, Swing UI building... • Provide a smaller core • and several smaller JARs per feature • Provide hooks for setting up DGM methods,
    • 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
    • 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
    • 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")
    • Extension modules • Create your own module • contribute instance extension methods Same structure as Categories package  foo class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        } } //  usage:  "Guillaume".introduces("Cédric")
    • Extension modules • Create your own module • contribute class extension methods package  foo class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        } } //  usage:  String.hi()
    • 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
    • Groovy 2.0 bird’s eye view Java 7 Static TypeA more Project Checkingmodular CoinGroovy Invoke Static Compilation Dynamic
    • Groovy 2.0 bird’s eye view Java 7 Project Coin Invoke Dynamic
    • Binary literals • We had decimal, octal and hexadecimal notations for number literals • We can now use binary representations too int  x  =  0b10101111 assert  x  ==  175   byte  aByte  =  0b00100001 assert  aByte  ==  33   int  anInt  =  0b1010000101000101 assert  anInt  ==  41285
    • 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
    • Multicatch • One block for multiple exception caught • rather than duplicating the blocktry  {        /*  ...  */}  catch(IOException  |  NullPointerException  e)  {        /*  one  block  to  treat  2  exceptions  */}
    • 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
    • Groovy 2.0 bird’s eye view Java 7 Static TypeA more Project Checkingmodular CoinGroovy Invoke Static Compilation Dynamic
    • Groovy 2.0 bird’s eye view Static Type Checking Static Compilation
    • 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
    • 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 }
    • Typos in a variable or method import  groovy.transform.TypeChecked   void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()Compilation   errors!        def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme }
    • Typos in a variable or methodAnnotation can be at class or method level import  groovy.transform.TypeChecked   void  method()  {}   @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()Compilation   errors!        def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme }
    • 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
    • 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
    • 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 }
    • Wrong return types //  checks  if/else  branch  return  values @TypeChecked int  method()  { Compilation        if  (true)  {  String  } error!        else  {  42  } } //  works  for  switch/case  &  try/catch/finally   //  transparent  toString()  implied @TypeChecked String  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name }
    • 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        } }
    • 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() }
    • Instanceof checks @TypeChecked   void  test(Object  val)  {        if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
    • Instanceof checks @TypeChecked   void  test(Object  val)  { No need        if  (val  instanceof  String)  {                println  val.toUpperCase() for casts        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } }
    • Instanceof checks @TypeChecked   void  test(Object  val)  { No need        if  (val  instanceof  String)  {                println  val.toUpperCase() for casts        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        } } Can call String#multiply(int) from the Groovy Development Kit
    • 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] }
    • 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>
    • 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>
    • 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! }
    • 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) • But compile-time metaprogramming works • as long as proper type information is defined
    • Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() }
    • Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Not allowed: metaClass property is dynamic
    • Gotcha: runtime metaprogramming @TypeChecked   void  test()  {        Integer.metaClass.foo  =  {}        123.foo() } Method not Not allowed: recognized metaClass property is dynamic
    • Gotcha: explicit type for closures @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {                it.toUpperCase()  //  Not  OK        } }
    • Gotcha: explicit type for closures @TypeChecked  test()  {        ["a",  "b",  "c"].collect  {  String  it  -­‐>                it.toUpperCase()  //  OK,  it’s  a  String        } }
    • Closure shared variables @TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK! }
    • 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! }
    • Closure shared variables var assigned in the closure: « shared closure variable » @TypeChecked  test()  { Impossible to        def  var  =  "abc"               ensure the        def  cl  =  {  var  =  new  Date()  } assignment        if  (random)  cl()really happens        var.toUpperCase()    //  Not  OK! }
    • Closure shared variables var assigned in the closure: « shared closure variable » @TypeChecked  test()  { Impossible to        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
    • Closure shared variables class  A                      {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK! }
    • Closure shared variables class  A                      {  void  foo()  {}  } class  B  extends  A  {  void  bar()  {}  } @TypeChecked  test()  {        def  var  =  new  A()        def  cl  =  {  var  =  new  B()  }        if  (random)  cl()        var.foo()      //  OK! } var is at least an instance of A
    • 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
    • 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
    • Static Compilation: disadvantages • But you loose: • Dynamic features • metaclass changes, categories, etc. • Dynamic method dispatch • although as close as possible to « dynamic » Groovy
    • 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() }
    • 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)
    • What about performance? Pi (π) Binary Fibonacci quadrature trees Java 191 ms 97 ms 3.6 s 1.7 1.8 2.0 Static 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
    • Back to the future...
    • Full invoke dynamic support Groovy 2.1 • In Groovy 2.0, not all call paths were going through invoke dynamic calls • essentially method calls only • still used call site caching techniques • On JDK 7 with the « indy » JAR, Groovy 2.1 uses invoke dynamic everywhere • On JDK < 7, still uses call site caching
    • @DelegatesTo Groovy 2.1 • Static type checking works nicely for certain Domain-Specific Languages • command chains, extension methods, etc. • But for changes of delegation within closures, it’s not helping • often used by DSLs like within Gradle • Enters @DelegatesTo!
    • @DelegatesTo Groovy 2.1class  ExecSpec  {        void  foo()}
    • @DelegatesTo Groovy 2.1class  ExecSpec  {        void  foo()}void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}
    • @DelegatesTo Groovy 2.1class  ExecSpec  {        void  foo()}void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}exec(spec)  {        foo()}
    • @DelegatesTo Groovy 2.1class  ExecSpec  {        void  foo()}void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}exec(spec)  { Static type checker        foo() doesn’t know about} that foo() method
    • @DelegatesTo Groovy 2.1void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}
    • @DelegatesTo Groovy 2.1 Annotate with: @DelegatesTo(ExecSpec)void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}
    • @DelegatesTo Groovy 2.1 • With a special delegation strategy void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c() }
    • @DelegatesTo Groovy 2.1 • With a special delegation strategy Annotate with: @DelegatesTo(value = ExecSpec, strategy = DELEGATE_FIRST) void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c() }
    • @DelegatesTo Groovy 2.1 • Use Target to specify the precise argument to delegate to void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
    • @DelegatesTo Groovy 2.1 • Use Target to specify the precise argument to delegate to@DelegatesTo.Target("id") void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
    • @DelegatesTo Groovy 2.1 • Use Target to specify the precise argument to delegate to@DelegatesTo.Target("id") @DelegatesTo(target = "id") void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c() }
    • @DelegatesTo Groovy 2.1 • For DSLs using Groovy closure delegation • Great for... • documenting APIs • IDE integration • code completion, code navigation... • working nicely with static type checking and static compilation
    • Custom type checking Groovy 2.1 • You can make Groovy’s static type checking even smarter, with your own smarts! • even smarter than Java’s :-) • Create your own type checker extension @TypeChecked(extensions  =                            MyExtension.groovy) void  exec()  {        //  code  to  be  further  checked... }
    • Custom type checking Groovy 2.1• Your own extension has access to an event-based API • onMethodSelection • methodNotFound • afterMethodCall • unresolvedVariable • beforeMethodCall • unresolvedProperty • unresolvedAttribute • afterVisitMethod • beforeVisitMethod • incompatibleAssignment
    • Custom type checking Groovy 2.1 MyExtension.groovy onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }
    • Custom type checking Groovy 2.1 MyExtension.groovy onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } Know your Groovy AST API well ;-)
    • Custom type checking Groovy 2.1 Doesn’t need MyExtension.groovy to be compiled onMethodSelection  {  expr,  method  -­‐>  ...  } afterMethodCall  {  mc  -­‐>  ...  } unresolvedVariable  {  var  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  } incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  } Know your Groovy AST API well ;-)
    • Alias annotations Groovy 2.1 • Ability to create meta-annotations combining and/or parameterizing other annotations • Works also for local AST transformations and their annotations
    • Alias annotations Groovy 2.1 @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {}
    • Alias annotations Groovy 2.1 @Immutable @ToString(excludes  =  ["age"]) @AnnotationCollector @interface  MyAlias  {} The « collector »
    • Alias annotations Groovy 2.1 Collected @Immutable @ToString(excludes  =  ["age"]) annotations @AnnotationCollector @interface  MyAlias  {} The « collector »
    • Alias annotations Groovy 2.1 Collected @Immutable @ToString(excludes  =  ["age"]) annotations @AnnotationCollector @interface  MyAlias  {} The « collector » Your own custom alias name
    • Alias annotations Groovy 2.1 Collected @Immutable @ToString(excludes  =  ["age"]) annotations @AnnotationCollector @interface  MyAlias  {} The « collector » Your own custom alias name @MyAlias class  Foo  {        String  name        int  age }
    • Alias annotations Groovy 2.1 Collected @Immutable @ToString(excludes  =  ["age"]) annotations @AnnotationCollector @interface  MyAlias  {} The « collector » Your own custom alias name @MyAlias class  Foo  { Use your        String  name concise alias        int  age }
    • Take control of your Groovy! Groovy 2.1 • Groovy 1.8 introduced compilation customizers • add imports, AST xforms, secure the AST... • With static type checking and static compilation, we received feedback from people wanting them applied « by default » • Allow to instruct the groovyc compiler with a configuration script • groovyc -configurator compConf.groovy Foo.groovy
    • Take control of your Groovy! Groovy 2.1 • Add a default @ToString transform import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers •              .ASTTransformationCustomizer config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) )
    • Take control of your Groovy! Groovy 2.1 • Add a default @ToString transform import  groovy.transform.ToString import  org.codehaus.groovy.control.customizers •              .ASTTransformationCustomizer config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString) ) Implicit «config» variable representing a CompilationConfiguration instance
    • Take control of your Groovy! Groovy 2.1 • You can use a builder syntax: config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  MyBean)  {                ast(ToString)        } }
    • Take control of your Groovy! Groovy 2.1 • You can use a builder syntax: config.customizers  {        //  apply  to  MyBean.groovy config.customizers  {        source(basename:  MyBean)  {        //  apply  to  *.gbean  files                ast(ToString)        source(extension:  .gbean)  {        }                ast(ToString) }        } }
    • Take control of your Groovy! Groovy 2.1 • You can use a builder syntax: config.customizers  {        //  apply  to  MyBean.groovy config.customizers  {        source(basename:  MyBean)  {        //  apply  to  *.gbean  files                ast(ToString) config.customizers  {        source(extension:  .gbean)  {        }        //  custom  filter  logic                  ast(ToString) }        //  with  compilation  units        } }        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)        } }
    • Roadmap Groovy 2.1 Groovy 4.0 2012 2013 2014 2014 Groovy 2.0 Groovy 3.0
    • Roadmap Groovy 2.1 Groovy 4.0 2012 2013 2014 2014 Groovy 2.0 Groovy 3.0
    • Roadmap Groovy 2.1 Groovy 4.0 2012 2013 2014 2014 Groovy 2.0 Groovy 3.0
    • End of 2012... and the world?2012GGeX End of the world
    • End of 2012... and the world?2012 DecGGeX 17-23 End of the world
    • End of 2012... and the world? Groovy 2.1 beta2012 DecGGeX 17-23 End of the world
    • End of 2012... and the world? Groovy 2.1 beta2012 DecGGeX 17-23 End of Recovering the world from GGeX
    • End of 2012... and the world? Groovy 2.1 beta2012 DecGGeX 17-23 End of Recovering the world from GGeX
    • End of 2012... and the world? Groovy 2.1 beta Christmas2012 DecGGeX 17-23 End of Recovering the world from GGeX
    • End of 2012... and the world? Groovy 2.1 beta Christmas2012 DecGGeX 17-23 End of Recovering the world from GGeX
    • End of 2012... and the world? Groovy 2.1 beta Christmas2012 DecGGeX 17-23 End of Recovering the world from GGeX
    • End of 2012... and the world? Groovy 2.1 beta Christmas2012 DecGGeX 17-23 End of Recovering Recovering the world from GGeX again !
    • Happy New Year! Jan 7-13
    • Happy New Year! Groovy 2.1 RC Jan 7-13
    • Happy New Year! Groovy 2.1 RC Jan Jan 7-13 14-21
    • Happy New Year! Groovy 2.1 RC Jan Jan 7-13 14-21 Wait for feedback
    • Happy New Year! Groovy 2.1 RC Potential 2nd RC Jan Jan 7-13 14-21 Wait for feedback
    • Happy New Year! Groovy 2.1 RC Potential 2nd RC Jan Jan Jan 7-13 14-21 22-29 Wait for feedback
    • Happy New Year! Groovy 2.1 RC Potential 2nd RC Jan Jan Jan 7-13 14-21 22-29 Wait for Groovy 2.1 feedback Final !
    • Back to 2013 and beyond Groovy 2.1 Groovy 4.0 2012 2013 2014 2014 Groovy 2.0 Groovy 3.0
    • GroovyThe infamous 3.0MOP 2
    • Groovy 4.0Antlr 4grammar
    • oovy λ GrJDK 4.0 8Lambdas
    • Summary (1/2) • As always, a rich and blossoming ecosystem • Groovy 2.0 • more modularity • static theme • static type checking • static compilation • JDK 7 theme • invoke dynamic support • project coin syntax enhancements
    • Summary (2/2) • Groovy 2.1 • complete indy support • @DelegatesTo • custom type checking for your DSLs • alias annotation • And beyond... • a new MOP (Meta-Object Protocol) • a new grammar with Antlr 4 • JDK 8 lambda support
    • Thank you! ge me Lafor lopment Guillau roovy Deve G H ead of m @g mail.co laforge rge Email: g @glafo /glaforg e : .to Twitter : http://gplus spot.com + pp Google p://glaforge.a tt Blog: h
    • Picture credits • London http://www.londonup.com/media/1251/Tower-Bridge-london-582331_1024_768.jpg • cherry blossom http://wallpaperswide.com/cherry_blossom_3-wallpapers.html • NKOTB http://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg • USA today http://www.adams-pr.com/images/uploads/USA_Today_logo.jpg • back to the future http://davidhiggerson.files.wordpress.com/2012/02/back-to-the-future-delorean.jpg • magnifying glass http://www.renders-graphiques.fr/image/upload/normal/loupe.png • Santa Claus http://icons.iconarchive.com/icons/fasticon/santa-claus/256/Happy-SantaClaus-icon.png • Champagne http://reallife101blogs.files.wordpress.com/2010/11/champagne_glasses2.jpg • that’s all folks http://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg • MOP http://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg • grammar http://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg