lift off with groovy 2 at javaone 2013

Post on 17-May-2015

1.805 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Presentations on the features of the Groovy 2.x line

TRANSCRIPT

© 2013 Guillaume Laforge. All rights reserved. Do not distribute without permission.

Guillaume Laforge @glaforge

Lift-off with Groovy 2 ...and beyond!

© 2013 Guillaume Laforge. All rights reserved. Do not distribute without permission.

Guillaume Laforge @glaforge

Lift-off with Groovy 2 ...and beyond!

Guillaume Laforge @glaforge

http://glaforge.appspot.com http://gplus.to/glaforge

Guillaume Laforge @glaforge

http://glaforge.appspot.com http://gplus.to/glaforge

Presentation will be uploaded tohttps://speakerdeck.com/glaforge

A dynamic language,optionally typed

Groovy

...statically type checkedand compiled as needed

Groovy

Syntax deriving from Java, thus easy to learn

Groovy

million downloadsin 2012

1.7

10

A blossomingEcosystem

GVM

Let’s start the engine

ModularityJava 7: Project Coin & invoke dynamicStatic type checking & compilation

Modularity

« Not everybody needs everything,all the time, at the same time! »

Groovy modularity

• The « groovy-all » weighted... 6 MB !

• In addition to the language, we have APIs:– template engine, Ant task scripting, Swing UI builder,

JMX builder...

• We want a lighter « core »– with APIs in the form of modules

• Ability to wire in « extension methods »

16

The new JARs

• One smaller core JAR of 3 MB

• Modules

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

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

– test– testng– json– xml

17

The new JARs

• One smaller core JAR of 3 MB

• Modules

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

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

– test– testng– json– xml

17

« Let’s go shopping »

Extension modules

• Create your own extension module– contribute instance methods

package  foo

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

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

19

Extension modules

• Create your own extension module– contribute instance methods

package  foo

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

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

Same structure as categories

19

Extension modules

• Create your own extension module– contribute static methods

20

package  foo

class  StaticStringExtension  {        static  hi(String  self)  {                "Hi!"        }}//  usage:  String.hi()

Extension module descriptor

• META-INF/– services/

• org.codehaus.groovy.runtime.ExtensionModule

moduleName  =  stringExtensionsmoduleVersion  =  1.0//  comma  separated  list  of  FQN  class  namesextensionClasses  =  foo.StringExtension//  comma  separated  list  of  FQN  class  namesstaticExtensionClasses  =  foo.StaticStringExtension

21

Java 7 theme

« Project Coin » syntaxInvoke Dynamic support

Binary literals

• In addition to decimal, octal and hexa• A new binary representation:

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

23

Underscores in literals

• Use underscores in number literals

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

25

Multi-catch exception blocks

• A single catch block to catch several exceptions at once, rather than duplicating blocks

try  {        /*  ...  */}  catch(IOException  |  NullPointerException  e)  {        /*  un  seul  bloc  */}

26

Woot!

JDK 7 Invoke Dynamic support

• A « flag » to compile with « indy »– we might propose a backport for JDK < 7

• Avantages– more runtime performance

•well... in theory...– In the long term, we might replace

•« call site caching » ➔ MethodHandles•« metaclass registry » ➔ ClassValues

– and the JIT « inlines » code more easily

28

A « static » theme

Static type checkingStatic compilation

Static type checking

• Goal: make the compiler grumpy!

– throw errors at compile-time• rather than at runtime

30

We don’t need dynamic features

all the time!

We don’t need dynamic features

all the time!

Nah !

Static type checking

• A « grumpy » compiler should...

– say when there’s a typoin a method or variable name

– complain when a non-existent method is called

– or on bad assignments or use a bad return type

32

Static type checking

• The compiler should infer types...

– less explicit types and casts

– fine grained type inference•« flow typing »•« lowest upper bound »

33

Static type checking

• But the compiler should understand extension methods

– allows a good level of dynamism, despite the additional restrictions

34

Typos

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

35

Typos

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilation error

35

Typos

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilation error

Compilation error

35

Typos

import  groovy.transform.TypeChecked  void  method()  {}  @TypeChecked  test()  {        //  Cannot  find  matching  method  metthhoood()        metthhoood()          def  name  =  "Guillaume"        //  variable  naamme  is  undeclared        println  naamme}

Compilation error

Compilation error

Annotation at the method or class level

35

Wrong variable assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

36

Wrong variable assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Compilation error

36

Wrong variable assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Compilation error

Compilation error

36

Wrong variable assignments

//  cannot  assign  value  of  type...  to  variable...int  x  =  new  Object()Set  set  =  new  Object()  String[]  strings  =  ['a','b','c']int  str  =  strings[0]  //  cannot  find  matching  method  plus()int  i  =  0i  +=  '1'

Compilation error

Compilation error

Compilation error

36

Wrong return type

//  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}

37

Wrong return type

//  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}

Compilation error

37

Wrong return type

//  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}

Compilation error

In the end, call StringBuilder’s toString()

37

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

38

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

Variable optionally typed

38

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

Variable optionally typed

Type String infered

38

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

Variable optionally typed

trim() method added dynamically by Groovy

Type String infered

38

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

Variable optionally typed

Array element type inferred

trim() method added dynamically by Groovy

Type String infered

38

Mix dynamic & statically checked code

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

39

Mix dynamic & statically checked code

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

Statically checked

39

Mix dynamic & statically checked code

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

Statically checked

Dynamic

39

Instanceof checks

@TypeChecked  void  test(Object  val)  {

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

40

Instanceof checks

@TypeChecked  void  test(Object  val)  {

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

No need for casts

40

Instanceof checks

@TypeChecked  void  test(Object  val)  {

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

No need for casts

No need for casts

40

Instanceof checks

@TypeChecked  void  test(Object  val)  {

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

No need for casts

No need for castsUnderstand GDK’s method:

String#multiply(int)

40

Lowest Upper Bound

• The smallest common « super » type– might be virtual (« non-denotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

41

Lowest Upper Bound

• The smallest common « super » type– might be virtual (« non-denotable »)

@TypeChecked  test()  {        //  an  integer  and  a  BigDecimal        return  [1234,  3.14]}

Infered type:List<T extends Number & Comparable & Serializable>

41

Flow typing

• Static type checking « follows » the type of values assigned into variables

@TypeChecked  test()  {        def  var  =  123                  //  int  infered        int  x  =  var                      //  var  is  an  int        var  =  "123"                      //  assign  a  String  into  var

       x  =  var.toInteger()      //  no  cast  needed

       var  =  123        x  =  var.toUpperCase()  //  error,  var  is  an  int  !}

42

Not really clean, your code!

Not really clean, your code!

Grmmpf...no!

Static type checking and dynamic code

•Type checking happens at compile-time– @TypeChecked doesn’t change behavior!

• do not confound with static compilation

• Most dynamic features can’t be checked– metaclass changes, categories...– dynamic variables from the « script binding »

• But compile-time metaprogramming OK– if enough type information is available

44

But if it ain’t dynamic, can we compile

it statically?

But if it ain’t dynamic, can we compile

it statically?

But of course!!!

Static compilation

• Given the code is statically type checked, lots of type information was infered...so we can as well compile statically !

– ie. generate the same bytecode as javac

• Also interesting when stuck on JDK < 7to gain performance improvements

46

Avantages of static compilation

• We gain:– type safety

• thanks to static type checking –the compiler builds upon it

– better performance• close to Java’s performance

– code immune to « monkey patching »•dynamic metaprogramming can interfere with your framework’s code

– smaller generated bytecode

47

I canz do what I want wiz your code

I canz do what I want wiz your code

Niark !

Drawbacks for static compilation

• We lose...

– Some dynamic features• metaclass changes, categories

– Method « dynamic dispatch » can differ• but thanks to type inference, it’s as close as «classical» Groovy as possible

49

Mix statically compiled code with dynamic

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

50

Mix statically compiled code with dynamic

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

Statically compiled

50

Mix statically compiled code with dynamic

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

Statically compiled

Dynamic

50

Mix statically compiled code with dynamic

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

Statically compiled

Dynamic

Call a method with

dynamic content

50

Mix statically compiled code with dynamic

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

Statically compiled

Dynamic

Call a method with

dynamic content

Method signatures are a contract!

50

What about performance?

• Comparisons between:

– Java

– Groovy•with static compilation (Groovy 2.0)•with primitive type optimization (Groovy 1.8)•no optimization (Groovy 1.7)

51

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.x

52

...and now, ontoGroovy 2.1

Complete Invoke Dynamic supportMeta-annotationsAdvanced compiler configurationType checker extensions

Invoke Dynamic

Complete support of Invoke Dynamic

Meta-annotations

One annotationto rule them all!

Meta-annotations

• Create meta-annotations which combine and/or parameterize other annotations

• And which work with AST transformations

56

Meta-annotations

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

57

Meta-annotations

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

Collected annotations

57

Meta-annotations

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

Collected annotations

The collector

57

Meta-annotations

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

Collected annotations

The collector

Your own annotation

alias

57

Meta-annotations

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

@MyAliasclass  Person  {        String  name        int  age}

Collected annotations

The collector

Your own annotation

alias

57

Meta-annotations

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

@MyAliasclass  Person  {        String  name        int  age}

Collected annotations

The collector

Your own annotation

aliasUse your meta-

annotation

57

@DelegatesTo annotation

Richer tooling supportfor Domain-Specific Languages

@DelegatesTo annotation

• Static type checking works fine with a certain range of DSLs– « command chains », extension methods...

• But less for DSLs using closure delegation– often used by DSLs like in Gradle

task  copyTask(type:  Copy)  {        from  'src/main/webapp'        into  'build/explodedWar'}

59

@DelegatesTo annotation

exec(spec)  {        foo()}

60

@DelegatesTo annotationclass  ExecSpec  {        void  foo()}

exec(spec)  {        foo()}

60

@DelegatesTo annotationclass  ExecSpec  {        void  foo()}

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

exec(spec)  {        foo()}

60

@DelegatesTo annotationclass  ExecSpec  {        void  foo()}

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

exec(spec)  {        foo()}

The static type checker doesn’t know about method foo()

60

@DelegatesTo annotationclass  ExecSpec  {        void  foo()}

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

exec(spec)  {        foo()}

Annotate with @DelegatesTo(ExecSpec)

The static type checker doesn’t know about method foo()

60

@DelegatesTo annotation

• With another delegation strategy

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

61

@DelegatesTo annotation

• With another delegation strategy

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

Annotate with@DelegatesTo(value = ExecSpec,

strategy = DELEGATE_FIRST)

61

@DelegatesTo annotation

• Very interesting for DSLs using closure’s delegation strategy

• Excellent for...– documenting your APIs– the integration within the IDE

• code completion, code navigation

– works well with static type checking and static compilation

62

Extend the static type checker

To go even further than Java itself !

Extend the static type checker

• Extend the type checker to make it smarter!– even smarter than Java’s! :-)

• By creating your own extension

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

64

Extend the static type checker

• Extend the type checker to make it smarter!– even smarter than Java’s! :-)

• By creating your own extension

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

We could use a meta-annotation

64

Extend the static type checker

• Help the static type checker when...

– impossible to infer types– no matching method found– no matching attribute found– on wrong variable assignment– ...

65

Extend the static type checker

• Your extension has access to an event-oriented API

66

• onMethodSelection

• afterMethodCall• beforeMethodCall

• afterVisitMethod• beforeVisitMethod

• methodNotFound• unresolvedVariable• unresolvedProperty• unresolvedAttribute

• incompatibleAssignment

Extend the static type checker

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

67

Extend the static type checker

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

MyExtension.groovy

67

Extend the static type checker

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

MyExtension.groovy

Learn your Groovy AST!

67

Extend the static type checker

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

MyExtension.groovy

Learn your Groovy AST!

No need to be pre-compiled

67

Extend the static type checker

• A few examples

– check that a string is a valid SQL query

– check the arguments and types of sprintf() method calls so they match the pattern

68

Compiler configuration

Custom base script classConfiguration script

Configuration DSL

Compiler customization

• Groovy 1.8 introduced « customizers »– add imports transparently– apply AST transformations by default– filter / secure scripts

• With the « static type checker » and « static compilation », we were asked if we could apply them by default

70

Compiler customization

• New options

– --basescript to define a base script class for your scripts

– --configscript to indicate a script to configure the CompilerConfiguration object

71

Compiler customization

• Add the @ToString AST transformation

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

configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

72

Compiler customization

• Add the @ToString AST transformation

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

configuration.addCompilationCustomizer(        new  ASTTransformationCustomizer(ToString))

CompilerConfiguration instance,injected by default

72

Compiler customization

• A small DSL to configure the customization

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

73

Compiler customization

• A small DSL to configure the customization

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

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

73

Compiler customization

• A small DSL to configure the customization

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

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

configuration.customizers  {        //  custom  filter  logic        source(unitValidator:  {  unit  -­‐>  ...  })  {                ast(ToString)                imports  {                        staticStar  'java.lang.Math'                }        }}

73

To learn more...Groovy 2.0http://groovy.codehaus.org/Groovy+2.0+release+notes

Groovy 2.1http://groovy.codehaus.org/Groovy+2.1+release+notes

And what’s next?Groovy 2.2, 2.3 & 3 !

New « MOP »New Grammar with Antlr v4Java 8 Lambdas support

A few words about the roadmap

2014 2014 20132012

Groovy 2.1

Groovy 2.0Groovy 2.0 Groovy 2.2

Groovy 2.3

76

Groovy 3.0

A few words about the roadmap

2014 2014 20132012

Groovy 2.1

Groovy 2.0Groovy 2.0 Groovy 2.2

Groovy 2.3

76

Groovy 3.0

A few words about the roadmap

2014 2014 20132012

Groovy 2.1

Groovy 2.0Groovy 2.0 Groovy 2.2

Groovy 2.3

76

Groovy 3.0

Groovy 2.2

Implicit closure coercion@Memoized transformation

DelegatingScript base script class

Implicit closure coercion

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

Given a predicate & a List method to filter according to that predicate...

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

Given a predicate & a List method to filter according to that predicate...

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

Given a predicate & a List method to filter according to that predicate...

Java 8 lambdas can be more concise than Groovy!

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

list.filter({  it.age  >  18  }  as  Predicate)

Given a predicate & a List method to filter according to that predicate...

Java 8 lambdas can be more concise than Groovy!

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

list.filter  {  it.age  >  18  }  

Given a predicate & a List method to filter according to that predicate...

Java 8 lambdas can be more concise than Groovy!

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

list.filter  {  it.age  >  18  }  

Given a predicate & a List method to filter according to that predicate...

Java 8 lambdas can be more concise than Groovy!

When no ambiguity, make coercion implicit!

78

Implicit closure coercion

interface  Predicate<T>  {        boolean  test(T  t)}

List<T>  filter(Predicate<T>  p)

list.filter((it)  -­‐>  it.age  >  18)

list.filter  {  it.age  >  18  }  

Given a predicate & a List method to filter according to that predicate...

Java 8 lambdas can be more concise than Groovy!

When no ambiguity, make coercion implicit!

Go beyond Java, by making it work on abstract classes too

78

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

79

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

Handy for DSLs!

79

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

Handy for DSLs!

name  =  "Guillaume"sayHi()

79

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

class  Person  {        String  name

       void  sayHi()  {                  println  "Hi  $name"          }}

Handy for DSLs!

name  =  "Guillaume"sayHi()

79

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

class  Person  {        String  name

       void  sayHi()  {                  println  "Hi  $name"          }}

Handy for DSLs!

name  =  "Guillaume"sayHi()

Use Person’s name property

79

DelegatingScript base script class

• Special base script class to delegate method calls and property accesses to a delegatee

class  Person  {        String  name

       void  sayHi()  {                  println  "Hi  $name"          }}

Handy for DSLs!

name  =  "Guillaume"sayHi()

Use Person’s name property

Call Person#sayHi()

79

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

80

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

Specify DelegatingScript base class

80

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

Specify DelegatingScript base class

Parse the script

80

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

Specify DelegatingScript base class

Parse the script

Define the delegate

80

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

Specify DelegatingScript base class

Parse the script

Define the delegate

Run the script

80

DelegatingScript base script class

• Integration example:

def  cc  =  new  CompilerConfiguration()cc.scriptBaseClass  =  DelegatingScript.class.name

def  sh  =  new  GroovyShell(cc)def  script  =  sh.parse(file)

def  p  =  new  Person()script.setDelegate(p)script.run()

assert  p.name  ==  "Guillaume"

Specify DelegatingScript base class

Parse the script

Define the delegate

Run the script

Be Happy!80

groovysh doc command

81

groovysh doc command

Launches your browser with the JavaDoc and GDK doc of the class

81

groovysh code completion

82

groovysh code completion

Import completion

82

groovysh code completion

Import completion

Method call completion

82

@Memoized transformation

• Piggypack on Closure’s own memoization capabilities, but applied to methods

@Memoized  int  expensiveOp(int  a,  int  b)  {        sleep  1000        return  a  +  b}//  one  second  to  returnexpensiveOp(1,  2)  //  immediate  result  returnedexpensiveOp(1,  2)

83

Miscelanous improvements

• Precompiled type checking extensions

• Further tweaks to Groovysh with code completion, better error reporting...

• Better syntax highlighting in Groovy Console

• Various dependency upgrades (Gradle, Ant)

@TypeChecked(extensions  =  'fqn.MyExtension')

84

Additional GDK methods...

• groupBy() on arrays

• combinations(Closure)

• collectMany() on Iterables

• JsonSlurper’s parse(File) and parse(URL)

assert  [[2,  3],  [4,  5,  6]]                    .combinations  {  x,  y  -­‐>  x*y  }  ==                                            [8,  12,  10,  15,  12,  18]

85

Likely inGroovy 2.3

TraitsGroovyDoc rewrite

New documentation & website

Trait implementation

87

Trait implementation

trait  FlyingAbility  {        String  fly()  {                "I  believe  I  can  fly!"        }}

87

Trait implementation

trait  FlyingAbility  {        String  fly()  {                "I  believe  I  can  fly!"        }}

A trait keyword applying the @Trait transformation

87

Trait implementation

trait  FlyingAbility  {        String  fly()  {                "I  believe  I  can  fly!"        }}

A trait keyword applying the @Trait transformation

class  Car  implements  FlyingAbility  {}

87

Trait implementation

trait  FlyingAbility  {        String  fly()  {                "I  believe  I  can  fly!"        }}

A trait keyword applying the @Trait transformation

class  Car  implements  FlyingAbility  {}

A class «implements» the trait

87

Trait implementation

trait  FlyingAbility  {        String  fly()  {                "I  believe  I  can  fly!"        }}

A trait keyword applying the @Trait transformation

class  Car  implements  FlyingAbility  {}

A class «implements» the trait

def  c  =  new  Car()assert  c.fly()  ==  "I  believe  I  can  fly!"

87

GroovyDoc rewrite

88

GroovyDoc rewrite

GroovyDoc != Sexy Doc

88

New documentation and website

• New reference documentation and guides using AsciiDoctor

• New website with a refreshed skin and the new content

89

Groovy 3

New MOPNew Antlr v4 grammarJDK 8 lambda support

MOP

2

Antlr 4grammar

λJDK

8

Summary

• A very rich and blossoming ecosystem•Groovy 2.0

– more modular– a static theme

• static type checking• static compilation

– JDK 7 theme• Invoke Dynamic support• Project Coin syntax enhancements

95

Summary

•Groovy 2.1– Invoke Dynamic support completed– @DelegatesTo annotation– type checker extensions for DSLs– meta-annotations

96

Summary

• Groovy 2.2 – implicit closure coercion– @Memoized transformation– DelegatingScript for script DSLs– groovysh improvements

97

Summary

• Groovy 2.3– traits– new GroovyDoc– new documentation– new website

98

Summary

• Groovy 3– a new MOP (Meta-Object Protocol)– a new grammar with Antlr v4– the support of JDK 8 and lambdas

99

Questions & Answers

Thank you! @glaforge

http://glaforge.appspot.com

http://gplus.to/glaforge

Image credits• lift-off: http://www.wpclipart.com/space/ships/space_shuttle/Space_Shuttle_liftoff.png

• anniversary: http://www.empowernetwork.com/fam/files/2013/03/happy_birthday_cake_with_candles-1920x1200.jpg

• cerisier: 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

• lunar module: http://www.clavius.org/img/lm-diag.gif

• tomates: http://www.infoescola.com/wp-content/uploads/2011/01/tomate.jpg

• patates: http://toooof.free.fr/blogs/captainslip/screenshots/pommes_de_terre.jpg

• coins: http://www.coins-jewelry.com/c22.png

• more coins: http://diamond-center.co.il/upload/articles/gold-coins1.jpg

• binary: http://okletsgo.co.uk/img/binary.jpg

• grumpy: https://si0.twimg.com/profile_images/3115998027/b47c180a703a5ffa7d1437a66f545dc0.jpeg

• singe: http://static.ddmcdn.com/gif/how-to-draw-animals-31.jpg

• warning: http://th07.deviantart.net/fs71/PRE/i/2012/261/8/6/warning_gangnam_style_zone_by_untoucheddesigns-d5f6bal.png

• coyote: http://nittygriddy.com/wp-content/uploads/2011/01/Wiley-Coyote-Help.jpg

• ring: http://img.banggood.com/images/upload/2012/limin/SKU028431_11.JPG

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

• work in progress: http://www.sbscompany.org/multimedia/immagini/work-in-progress.png

• tab key: http://www.meganga.com/wp-content/uploads/2012/03/Tab-Key-Word-Tutorials.jpg

• chronomètre: http://www.moineau-instruments.com/59-thickbox/chronometre-mecanique-1-10-t15-mn-2-fonctions.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

102

top related