groovy 2 and beyond

Post on 17-May-2015

2.616 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

"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

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

GV

M

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 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

Groovy 2.0 bird’s eye view

A more modular Groovy

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– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

The new JARs

• A smaller JAR: 3MB

• Modules

– console– docgenerator– groovydoc– groovysh– ant– bsf

– jsr-223– jmx– sql– swing– servlet– templates

– test– testng– json– xml

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

package  foo

class  StringExtension  {        static  introduces(String  self,  String  name)  {                "Hi  ${name),  I’m  ${self}"        }}

//  usage:  "Guillaume".introduces("Cédric")

Same structureas Categories

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  =  stringExtensionsmoduleVersion  =  1.0//  comma-­‐separated  list  of  classesextensionClasses  =  foo.StringExtension//  comma-­‐separated  list  of  classesstaticExtensionClasses  =  foo.StaticStringExtension

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

Groovy 2.0 bird’s eye view

Java 7Project

Coin

Invoke Dynamic

Binary literals

• We had decimal, octal and hexadecimal notations for number literals

• We can now use binary representations too

int  x  =  0b10101111assert  x  ==  175  byte  aByte  =  0b00100001assert  aByte  ==  33  int  anInt  =  0b1010000101000101assert  anInt  ==  41285

Underscore in literals

• Now we can also add underscores in number literals for more readability

long  creditCardNumber  =  1234_5678_9012_3456Llong  socialSecurityNumbers  =  999_99_9999Lfloat  monetaryAmount  =  12_345_132.12long  hexBytes  =  0xFF_EC_DE_5Elong  hexWords  =  0xFFEC_DE5Elong  maxLong  =  0x7fff_ffff_ffff_ffffLlong  alsoMaxLong  =  9_223_372_036_854_775_807Llong  bytes  =  0b11010010_01101001_10010100_10010010

Multicatch

• One block for multiple exception caught

• rather than duplicating the block

try  {        /*  ...  */}  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 7Project

Coin

Invoke Dynamic

A more modular Groovy

Static Type Checking

Static Compilation

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()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilationerrors!

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}

Compilationerrors!

Annotation can be atclass or method level

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  =  0i  +=  '1'

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  =  0i  +=  '1'

Compilationerrors!

Wrong return types

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Wrong return types

//  checks  if/else  branch  return  values@TypeCheckedint  method()  {        if  (true)  {  'String'  }        else  {  42  }}//  works  for  switch/case  &  try/catch/finally  //  transparent  toString()  implied@TypeCheckedString  greeting(String  name)  {        def  sb  =  new  StringBuilder()        sb  <<  "Hi  "  <<  name}

Compilationerror!

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

@TypeCheckedString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  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)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

No needfor casts

Instanceof checks

@TypeChecked  void  test(Object  val)  {

       if  (val  instanceof  String)  {                println  val.toUpperCase()        }  else  if  (val  instanceof  Number)  {                println  "X"  *  val.intValue()        }}

No needfor casts

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()}

Not allowed:metaClass property

is dynamic

Method notrecognized

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

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Impossible to ensure the

assignment really happens

Closure shared variables

@TypeChecked  test()  {        def  var  =  "abc"                      def  cl  =  {  var  =  new  Date()  }        if  (random)  cl()        var.toUpperCase()    //  Not  OK!}

var assigned in the closure: « shared closure variable »

Impossible to ensure the

assignment really happens

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

@CompileStaticString  greeting(String  name)  {        //  call  method  with  dynamic  behavior        //  but  with  proper  signature        generateMarkup(name.toUpperCase())}  //  usual  dynamic  behaviorString  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?

Fibonacci Pi (π) quadrature

Binarytrees

Java

Staticcompilation

Primitive optimizations

No prim.optimizations

191 ms 97 ms 3.6 s

197 ms 101 ms 4.3 s

360 ms 111 ms 23.7 s

2590 ms 3220 ms 50.0 s1.7

1.8

2.0

Back to the future...

Full invoke dynamic support

• 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

Groovy

2.1

@DelegatesTo

• 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!

Groovy

2.1

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

@DelegatesTo Groovy

2.1

class  ExecSpec  {        void  foo()}

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

exec(spec)  {        foo()}

Static type checker doesn’t know about that foo() method

@DelegatesTo Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

Annotate with:@DelegatesTo(ExecSpec)

@DelegatesTo

• With a special delegation strategy

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

@DelegatesTo

• With a special delegation strategy

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c.resolveStrategy  =  DELEGATE_FIRST        c()}

Annotate with:@DelegatesTo(value = ExecSpec, strategy = DELEGATE_FIRST)

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target("id")

@DelegatesTo

• Use Target to specify the precise argument to delegate to

Groovy

2.1

void  exec(ExecSpec  sp,  Closure  c)  {        c.delegate  =  sp        c()}

@DelegatesTo.Target("id") @DelegatesTo(target = "id")

@DelegatesTo

• 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

Groovy

2.1

Custom type checking

• 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

Groovy

2.1

@TypeChecked(extensions  =                            'MyExtension.groovy')void  exec()  {        //  code  to  be  further  checked...}

• Your own extension has access to an event-based API

Custom type checking

• onMethodSelection

• afterMethodCall

• beforeMethodCall

• afterVisitMethod

• beforeVisitMethod

• methodNotFound

• unresolvedVariable

• unresolvedProperty

• unresolvedAttribute

• incompatibleAssignment

Groovy

2.1

Custom type checking

onMethodSelection  {  expr,  method  -­‐>  ...  }afterMethodCall  {  mc  -­‐>  ...  }unresolvedVariable  {  var  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }methodNotFound  {  receiver,  name,  argList,  argTypes,  call  -­‐>  ...  }incompatibleAssignment  {  lhsType,  rhsType,  expr  -­‐>  ...  }

Groovy

2.1

MyExtension.groovy

Custom type checking

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 ;-)

Groovy

2.1

MyExtension.groovy

Custom type checking

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 ;-)

Groovy

2.1

MyExtension.groovyDoesn’t need

to be compiled

Alias annotations

• Ability to create meta-annotations combining and/or parameterizing other annotations

• Works also for local AST transformations and their annotations

Groovy

2.1

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Collected annotations

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

The « collector »

Your own custom alias name

Collected annotations

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

@MyAliasclass  Foo  {        String  name        int  age}

The « collector »

Your own custom alias name

Collected annotations

Alias annotations

@Immutable@ToString(excludes  =  ["age"])@AnnotationCollector@interface  MyAlias  {}

Groovy

2.1

@MyAliasclass  Foo  {        String  name        int  age}

The « collector »

Your own custom alias name

Use your concise alias

Collected annotations

Take control of your Groovy!

• 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

Groovy

2.1

Take control of your Groovy!

• Add a default @ToString transform

Groovy

2.1

import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Take control of your Groovy!

• Add a default @ToString transform

Groovy

2.1

import  groovy.transform.ToStringimport  org.codehaus.groovy.control.customizers              .ASTTransformationCustomizer

config.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

Implicit «config» variable representing a CompilationConfiguration instance

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

Take control of your Groovy!

• You can use a builder syntax:

Groovy

2.1

config.customizers  {        //  apply  to  MyBean.groovy        source(basename:  'MyBean')  {                ast(ToString)        }}

config.customizers  {        //  apply  to  *.gbean  files        source(extension:  '.gbean')  {                ast(ToString)        }}

config.customizers  {        //  custom  filter  logic          //  with  compilation  units        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)        }}

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

Roadmap

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

End of 2012... and the world?

2012GGeX

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

End of the world

End of 2012... and the world?

Dec17-23

2012GGeX

Groovy 2.1 beta

Recoveringfrom GGeX

Christmas

Recoveringagain !

End of the world

Happy New Year!

Jan7-13

Happy New Year!

Jan7-13

Groovy 2.1 RC

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Happy New Year!

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Potential 2nd RC

Happy New Year!

Jan22-29

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Potential 2nd RC

Happy New Year!

Jan22-29

Jan14-21

Jan7-13

Groovy 2.1 RC

Wait for feedback

Groovy 2.1Final !

Potential 2nd RC

Back to 2013 and beyond

2014 2014 20132012

Groovy 2.1 Groovy 4.0

Groovy 3.0Groovy 2.0

The infamous

MOP

2Groovy

3.0

Antlr 4grammar

Groovy

4.0

λJDK 8

Lambdas

Groovy

4.0

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

Picture credits

• Londonhttp://www.londonup.com/media/1251/Tower-Bridge-london-582331_1024_768.jpg

• cherry blossomhttp://wallpaperswide.com/cherry_blossom_3-wallpapers.html

• NKOTBhttp://images1.fanpop.com/images/photos/2300000/nkotb-new-kids-on-the-block-2314664-1280-960.jpg

• USA todayhttp://www.adams-pr.com/images/uploads/USA_Today_logo.jpg

• back to the futurehttp://davidhiggerson.files.wordpress.com/2012/02/back-to-the-future-delorean.jpg

• magnifying glasshttp://www.renders-graphiques.fr/image/upload/normal/loupe.png

• Santa Claushttp://icons.iconarchive.com/icons/fasticon/santa-claus/256/Happy-SantaClaus-icon.png

• Champagnehttp://reallife101blogs.files.wordpress.com/2010/11/champagne_glasses2.jpg

• that’s all folkshttp://4.bp.blogspot.com/-wJxosualm48/T4M_spcUUjI/AAAAAAAAB8E/njfLjNZQdsc/s1600/thats-all-folks.jpg

• MOPhttp://imagethumbnails.milo.com/024/913/894/trimmed/24913521_25989894_trimmed.jpg

• grammarhttp://edudemic.com/wp-content/uploads/2012/11/connected-learner-grammar.jpg

top related