SlideShare a Scribd company logo
1 of 149
Groovy Update
What’s new in Groovy 1.8,
and what’s cooking in 1.9!




  Guillaume Laforge
  Groovy Project Manager
  SpringSource / VMware
Guillaume Laforge

• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
  at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action

• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
  Devoxx, The Spring Experience, SpringOne, JAX, Dynamic
  Language World, IJTC, and more...


                                                      2
Guillaume Laforge

• Groovy Project Manager
• JSR-241 Spec Lead
• Head of Groovy Development
  at SpringSource / VMWare
• Initiator of the Grails framework
• Creator of the Gaelyk toolkit
• Co-author of Groovy in Action

• Speaker: JavaOne, QCon, JavaZone, Sun TechDays,
  Devoxx, The Spring Experience, SpringOne, JAX, Dynamic
  Language World, IJTC, and more...


                                                      2
Groovy 1.7




             3
Groovy 1.7




185
             3
Groovy 1.7




185k
             3
Groovy 1.7




185k   FIRST MONTH
       AFTER RELEASE
                       3
Groovy 1.7




             k
                 3
Groovy 1.7




177k   SECOND MONTH
       AFTER RELEASE
                       3
Groovy 1.7




             k
                 3
Groovy 1.7




362k
 USERS?
             3
?
TIP OF
THE
ICEBERG
Agenda




         5
Agenda

• What’s new in Groovy 1.8?
  – Nicer DSLs with command chains expressions
  – Runtime performance improvements
  – GPars bundled for taming your multicores
  – Closure enhancements
  – Builtin JSON support
  – New AST transformations
  – Miscelanous




                                                 5
Agenda

• What’s new in Groovy 1.8?
  – Nicer DSLs with command chains expressions
  – Runtime performance improvements
  – GPars bundled for taming your multicores
  – Closure enhancements
  – Builtin JSON support
  – New AST transformations
  – Miscelanous
• What’s cooking for Groovy 1.9?
  – Continued runtime performance improvements
  – Alignments with JDK 7
    • Project Coin (small language changes)
    • InvokeDynamic

                                                 5
Command chains expressions




                             6
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println




                                                               6
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println




                                                               6
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)




                                                               6
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)




                                                               6
Command chains expressions


• A grammar improvement allowing you to
  drop dots & parens when chaining method calls
  – an extended version of top-level statements like println


• Less dots, less parens allow you to
  – write more readable business rules
  – in almost plain English sentences
    • (or any language, of course)


• Let’s have a look at some examples


                                                               6
Command chains expressions




      
turn
left

then
right





                                7
Command chains expressions

      Alternation of
      method names




      
turn
left

then
right





                                7
Command chains expressions

      Alternation of
      method names




      
turn
left

then
right



                         and parameters
                       (even named ones)




                                           7
Command chains expressions




      
turn
left

then
right





                                7
Command chains expressions




       Equivalent to:


      




(



).



(




)
      
turn
left

then
right





                                7
LookM  a!
N op are ns,
no do ts!
Command chains expressions



    Before... we used to do...



 take
2.pills,
of:
chloroquinine,
after:
6.hours




                                              9
Command chains expressions



    Before... we used to do...



 take
2.pills,
of:
chloroquinine,
after:
6.hours


    Normal argument




                                              9
Command chains expressions



    Before... we used to do...



 take
2.pills,
of:
chloroquinine,
after:
6.hours


    Normal argument              Named arguments




                                                   9
Command chains expressions



     Before... we used to do...



 take
2.pills,
of:
chloroquinine,
after:
6.hours


     Normal argument              Named arguments


  Woud call:
  def
take(Map
m,
Quantity
q)

                                                    9
Command chains expressions



     Now, even less punctuation!



 take
2.pills

of

chloroquinine

after

6.hours




                                              10
Command chains expressions



     Now, even less punctuation!



 



(






).


(












).





(






)
 take
2.pills

of

chloroquinine

after

6.hours




                                              10
Command chains expressions

      //
environment
initialization
      Integer.metaClass.getPills
{
‐>
delegate
}
      Integer.metaClass.getHours
{
‐>
delegate
}
      

      //
variable
injection
      def
chloroquinine
=
/*...*/
      





  {                                                 }
      //
implementing
the
DSL
logic
      def
take(n)
{
      



[of:
{
drug
‐>
      







[after:
{
time
‐>
/*...*/
}]
      



}]
      }

      //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
      take
2.pills
of
chloroquinine
after
6.hours

                                                    11
Command chains expressions




 take
2.pills

of

chloroquinine

after

6.hours




                                              12
Command chains expressions




 take
2.pills

of

chloroquinine

after

6.hours


                ... some dots remain ...




                                              12
Command chains expressions



    We could cheat a bit...



 take
2

pills
of

chloroquinine
6

hours
after




                                              13
Command chains expressions



    We could cheat a bit...



 



(
).




(

).












(
).




(




)
 take
2

pills
of

chloroquinine
6

hours
after




                                              13
Cheating
is playing
   with the
 language
Command chains expressions



     Still doable without cheating though



 take
2

pills
of

chloroquinine
after

6
hours




                                              15
Command chains expressions



     Still doable without cheating though



 



(
).




(

).












(




).
(




)
 take
2

pills
of

chloroquinine
after

6
hours




                                              15
Command chains expressions


      //
variable
injection
      def
(of,
after,
hours)
=
/*...*/
      

      //
implementing
the
DSL
logic




  {                                                 }
      def
take(n)
{
      



[pills:
{
of
‐>
      







[chloroquinine:
{
after
‐>
      











['6':
{
time
‐>
}]
      







}]
      



}]
      }

      //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
      take
2
pills
of
chloroquinine
after
6
hours


                                                    16
Command chains expressions




                             17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)




                                               17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor




                                               17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation




                                               17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good




                                               17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures




                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}




                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens




                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names




                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms


                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names
 





(


).







.



(




)

 //
possible
with
an
odd
number
of
terms
 take
3

cookies

                                                    17
Command chains expressions

 //
methods
with
multiple
arguments
(commas)
 take
coffee

with
sugar,
milk

and
liquor
 



(





).



(










).


(





)

 //
leverage
named‐args
as
punctuation
 check
that:
margarita

tastes
good
 




(














).





(



)

 //
closure
parameters
for
new
control
structures
 given
{}

when
{}

then
{}
 




(

).



(

).



(

)

 //
zero‐arg
methods
require
parens
 select
all

unique()
from
names
 





(


).







.



(




)

 //
possible
with
an
odd
number
of
terms
 take
3

cookies
 



(
).

                                                    17
Runtime performance improvements

• Significant runtime improvements
  for primitive int operations
  – classical Fibonacci example x13 faster!
  – almost as fast as Java


• Some direct method calls on this

• But there’s more to come!
  – in particular for all the primitive types




                                                18
GPars bundled


• GPars is bundled in the Groovy distribution

• GPars covers a wide range of parallel and concurrent
  paradigms
  – actors, fork/join, dataflow, agents, STM...




                                                         19
Closure enhancements


• Closure annotation parameters

• Some more functional flavor
  – composition
  – trampoline
  – memoization


• Currying improvements




                                  20
Closure annotation parameters

    @Retention(RetentionPolicy.RUNTIME)
    @interface
Invariant
{




    



Class
value()
//
a
closure
class
    }
    


{   @Invariant({
number
>=
0
})
    class
Distance
{




    



float
number




    



String
unit
    }

    

    def
d
=
new
Distance(number:
10,
unit:
"meters")

    def
anno
=
Distance.getAnnotation(Invariant)
    def
check
=
anno.value().newInstance(d,
d)
    assert
check(d)

                                                    21
Closure annotation parameters

    @Retention(RetentionPolicy.RUNTIME)
    @interface
Invariant
{




    



Class
value()
//
a
closure
class
    }
    


{   @Invariant({
number
>=
0
})
    class
Distance
{




    



float
number



               an’s G
                                              Cont racts
    



String
unit            P oor-m
    }

    

    def
d
=
new
Distance(number:
10,
unit:
"meters")

    def
anno
=
Distance.getAnnotation(Invariant)
    def
check
=
anno.value().newInstance(d,
d)
    assert
check(d)

                                                      21
Closure composition

    def
plus2

=
{
it
+
2
}
    def
times3
=
{
it
*
3
}

    

{   def
times3plus2
=
plus2
<<
times3
    assert
times3plus2(3)
==
11
    assert
times3plus2(4)
==
plus2(times3(4))

    

{   def
plus2times3
=
times3
<<
plus2
    assert
plus2times3(3)
==
15
    assert
plus2times3(5)
==
times3(plus2(5))

    

    //
reverse
composition
{   assert
times3plus2(3)
==
(times3
>>
plus2)(3)

                                                    22
Closure trampoline




                     23
Closure trampoline

def
factorial

factorial
=
{
int
n,
BigInteger
accu
=
1G
‐>

                                            





if
(n
<
2)
return
accu









factorial.trampoline(n
‐
1,
n
*
accu)
}.trampoline()


assert
factorial(1)



==
1
assert
factorial(3)



==
1
*
2
*
3
assert
factorial(1000)
==
402387260...



                                          23
Closure memoization




                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately






                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 





                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)
 





                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)
 

 //
at
most
10
invocations
cached




                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)
 

 //
at
most
10
invocations
cached
 def
plusAtMost
=
{
...
}.memoizeAtMost(10)





                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)
 

 //
at
most
10
invocations
cached
 def
plusAtMost
=
{
...
}.memoizeAtMost(10)


 //
between
10
and
20
invocations
cached


                                                      24
Closure memoization

 def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()

 assert
plus(1,
2)
==
3
//
after
1000ms
 assert
plus(1,
2)
==
3
//
return
immediately
 assert
plus(2,
2)
==
4
//
after
1000ms
 assert
plus(2,
2)
==
4
//
return
immediately


 

 //
at
least
10
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeAtLeast(10)
 

 //
at
most
10
invocations
cached
 def
plusAtMost
=
{
...
}.memoizeAtMost(10)


 //
between
10
and
20
invocations
cached
 def
plusAtLeast
=
{
...
}.memoizeBetween(10,
20)

                                                      24
Currying improvements




                        25
Currying improvements

  //
right
currying
  def
divide
=
{
a,
b
‐>
a
/
b
}
  def
halver
=
divide.rcurry(2)
  assert
halver(8)
==
4


  





                                   25
Currying improvements

  //
right
currying
  def
divide
=
{
a,
b
‐>
a
/
b
}
  def
halver
=
divide.rcurry(2)
  assert
halver(8)
==
4


  

  //
currying
n‐th
parameter
  def
joinWithSeparator
=

  



{
one,
sep,
two
‐>
one
+
sep
+
two
}
  def
joinWithComma
=

  



joinWithSeparator.ncurry(1,
',
')
  assert
joinWithComma('a',
'b')
==
'a,
b'

                                             25
Builtin JSON support


• Consuming

• Producing

• Pretty-printing




                       26
Builtin JSON support


import
groovy.json.*


def
payload
=
new
URL(




"http://github.../json/commits/...").text


def
slurper
=
new
JsonSlurper()
def
doc
=
slurper.parseText(payload)


doc.commits.message.each
{
println
it
}




                                            27
Builtin JSON support


      import
groovy.json.*

      

      def
json
=
new
JsonBuilder()

      

      json.person
{




      



name
"Guillaume"
      



age
33




      



pets
"Hector",
"Felix"
      }

      println
json.toString()

                                      28
Builtin JSON support

  import
groovy.json.*

  

  println
JsonOutput.prettyPrint(
  



'''{"person":{"name":"Guillaume","age":33,'''
+

  



'''"pets":["Hector","Felix"]}}''')
  





                                                         29
Builtin JSON support

  import
groovy.json.*

  

  println
JsonOutput.prettyPrint(
  



'''{"person":{"name":"Guillaume","age":33,'''
+

  



'''"pets":["Hector","Felix"]}}''')
  


              {




              



"person":
{








              







"name":
"Guillaume",



                                            

              







"age":
33,








              







"pets":
[












              











"Hector",










                                            

              











"Felix"








              







]




              



}
              }


                                                         29
New AST transformations

• @Log                           • @Canonical
                                   – @ToString,
• @Field                           – @EqualsAndHashCode,
                                   – @TupleConstructor

• @AutoClone
                                 • @InheritConstructor
• @AutoExternalizable

                                 • @WithReadLock
• Controlling the execution of
  your code                      • @WithWriteLock
  – @ThreadInterrupt,
  – @TimedInterrupt,             • @ListenerList
  – @ConditionalInterrupt

                                                         30
@Log

• Four different loggers can be injected
  – @Log, @Commons, @Log4j, @Slf4j
• Possible to implement your own strategy

             import
groovy.util.logging.*

             

             @Log
             class
Car
{




             



Car()
{








             







log.info
'Car
constructed'


                                                

             



}
             }

             

             def
c
=
new
Car()


                                                    31
@Log

• Four different loggers can be injected
   – @Log, @Commons, @Log4j, @Slf4j
• Possible to implement your own strategy

             import
groovy.util.logging.*

             

             @Log
             class
Car
{




Guarded      



Car()
{








w/ an if     







log.info
'Car
constructed'


                                                

             



}
             }

             

             def
c
=
new
Car()


                                                    31
@Field

• Surprising scoping rules in scripts
  – variables are local to the run() method
  – variables aren’t visible in methods
     • although visually the variable is in a surrounding scope


• @Field creates a field in the script class


            @Field
List
awe
=
[1,
2,
3]
            def
awesum()
{
awe.sum()
}
            assert
awesum()
==
6


                                                                  32
Controlling code execution

• Your application may run user’s code
  – what if the code runs in infinite loops or for too long?
  – what if the code consumes too many resources?




                                                               33
Controlling code execution

• Your application may run user’s code
  – what if the code runs in infinite loops or for too long?
  – what if the code consumes too many resources?

• 3 new transforms at your rescue
  – @ThreadInterrupt: adds Thread#isInterrupted checks so your
    executing thread stops when interrupted
  – @TimedInterrupt: adds checks in method and closure bodies to
    verify it’s run longer than expected
  – @ConditionalInterrupt: adds checks with your own conditional
    logic to break out from the user code




                                                               33
Controlling code execution

• Your application may run user’s code
  – what if the code runs in infinite loops or for too long?
  – what if the code consumes too many resources?

• 3 new transforms at your rescue
  – @ThreadInterrupt: adds Thread#isInterrupted checks so your
    executing thread stops when interrupted
  – @TimedInterrupt: adds checks in method and closure bodies to
    verify it’s run longer than expected
  – @ConditionalInterrupt: adds checks with your own conditional
    logic to break out from the user code




                                                               33
Controlling code execution

• Your application may run user’s code
  – what if the code runs in infinite loops or for too long?
  – what if the code consumes too many resources?

• 3 new transforms at your rescue
  – @ThreadInterrupt: adds Thread#isInterrupted checks so your
    executing thread stops when interrupted
  – @TimedInterrupt: adds checks in method and closure bodies to
    verify it’s run longer than expected
  – @ConditionalInterrupt: adds checks with your own conditional
    logic to break out from the user code


• Also see compilation customizers later on

                                                               33
@ThreadInterrupt

    @ThreadInterrupt
    import
groovy.transform.ThreadInterrupt

    

    while
(true)
{


    



//
eat
lots
of
CPU
    }




                                               34
@ThreadInterrupt

      @ThreadInterrupt
      import
groovy.transform.ThreadInterrupt

      

      while
(true)
{

  {   



if
(Thread.currentThread.isInterrupted())
      







throw
new
InterruptedException()        }
      



//
eat
lots
of
CPU
      }




                                                          34
@ThreadInterrupt

       @ThreadInterrupt
       import
groovy.transform.ThreadInterrupt

       

       while
(true)
{

   {   



if
(Thread.currentThread.isInterrupted())
       







throw
new
InterruptedException()        }
       



//
eat
lots
of
CPU
       }


• Two optional annotation parameters available
  – checkOnMethodStart (true by default)
  – applyToAllClasses (true by default)

                                                           34
@TimedInterrupt

       @TimedInterrupt(10)
       import
groovy.transform.TimedInterrupt

       

       while
(true)
{
       



//
eat
lots
of
CPU
       }

• InterruptedException thrown when checks indicate code
  ran longer than desired

• Optional annotation parameters available
  – same as @ThreadInterrupt
  – value: for an amount of time duration
  – unit: for the time duration unit (TimeUnit.SECONDS)
                                                          35
@ConditionalInterrupt

• Specify your own condition to be inserted
  at the start of method and closure bodies
  – check for available resources, number of times run, etc.
• Leverages closure annotation parameters from Groovy 1.8

        @ConditionalInterrupt({
counter++
>
2
})
        import
groovy.transform.ConditionalInterrupt
        import
groovy.transform.Field

        

        @Field
int
counter
=
0


        100.times
{




        



println
'executing
script
method...'
        }


                                                               36
@ToString

• Provides a default toString() method to your types
• Available annotation options
  – includeNames, includeFields, includeSuper, excludes

          import
groovy.transform.ToString

          

          @ToString
          class
Person
{




          



String
name




          



int
age
          }

          

          println
new
Person(name:
'Pete',
age:
15)
          //
=>
Person(Pete,
15)


                                                          37
@EqualsAndHashCode

• Provides default implementations for equals() and
  hashCode() methods

          import
groovy.transform.EqualsAndHashCode

          

          @EqualsAndHashCode
          class
Coord
{




          



int
x,
y
          }

          

          def
c1
=
new
Coord(x:
20,
y:
5)
          def
c2
=
new
Coord(x:
20,
y:
5)

          

          assert
c1
==
c2
          assert
c1.hashCode()
==
c2.hashCode()



                                                       38
@TupleConstructor

• Provides a «classical» constructor with all properties
• Several annotation parameter options available

         import
groovy.transform.TupleConstructor

         

         @TupleConstructor

         class
Person
{




         



String
name




         



int
age
         }

         

         def
m
=
new
Person('Marion',
3)






         

         assert
m.name
==
'Marion'
         assert
m.age

==
3


                                                           39
@Canonical


• One annotation to rule them all!
  – @Canonical mixes together
    • @ToString
    • @EqualsAndHashCode
    • @TupleConstructor


• You can customize behavior by combining
  @Canonical and one of the other annotations




                                                40
@InheritConstructor

• Classes like Exception are painful when extended, as all
  the base constructors should be replicated




class
CustomException
extends
Exception
{




CustomException()























{
super()






}




CustomException(String
msg)













{
super(msg)



}




CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
}




CustomException(Throwable
t)












{
super(t)





}
}




                                                             41
@InheritConstructor

• Classes like Exception are painful when extended, as all
  the base constructors should be replicated


import
groovy.transform.*

@InheritConstructors
class
CustomException
extends
Exception
{




CustomException()























{
super()






}




CustomException(String
msg)













{
super(msg)



}




CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
}




CustomException(Throwable
t)












{
super(t)





}
}




                                                             41
@WithReadLock, @WithWriteLock

 import
groovy.transform.*

 

 class
ResourceProvider
{




 



private
final
Map<String,
String>
data
=
new
HashMap<>()
 

 



@WithReadLock




 



String
getResource(String
key)
{








 







return
data.get(key)




 



}





 

 



@WithWriteLock




 



void
refresh()
{








 







//reload
the
resources
into
memory




 



}
 }


                                                          42
@WithReadLock, @WithWriteLock

    import
groovy.transform.*

    

    class
ResourceProvider
{




    



private
final
Map<String,
String>
data
=
new
HashMap<>()
    

{   



@WithReadLock




    



String
getResource(String
key)
{








    







return
data.get(key)




    



}





    

{   



@WithWriteLock




    



void
refresh()
{








    







//reload
the
resources
into
memory




    



}
    }


                                                             42
Miscelanous



•   Compilation customizers
•   Java 7 diamond operator
•   Slashy and dollar slashy strings
•   New GDK methods
•   (G)String to Enum coercion




                                       43
Compilation customizers


• Ability to apply some customization to the Groovy
  compilation process

• Three available customizers
  – ImportCustomizer
  – SecureASTCustomizer
  – ASTTransformationCustomizer


• But you can implement your own



                                                      44
Imports customizer


def
configuration
=
new
CompilerConfiguration()


def
custo
=
new
ImportCustomizer()
custo.addStaticStar(Math.name)
configuration.addCompilationCustomizers(custo)



def
result
=
new
GroovyShell(configuration)




.evaluate("
cos
PI/3
")




                                             45
Applying an AST transformation

    def
configuration
=
new
CompilerConfiguration()

    configuration.addCompilationCustomizers(
    



new
ASTTransformationCustomizer(Log))

    

    new
GroovyShell(configuration).evaluate("""
    



class
Car
{








    







Car()
{












    











log.info
'Car
constructed'








    







}




    



}





    



log.info
'Constructing
a
car'




    



def
c
=
new
Car()
    """)



                                                      46
Secure AST customizer

             Idea: Implement an «arithmetic shell»
               Being able control what a user script is
               allowed to do: only arithmetic expressions

• Let’s setup our environment
  – some imports
  – an import customizer to import java.lang.Math.*
  – prepare a secure AST customizer
import
org.codehaus.groovy.control.customizers.*
import
org.codehaus.groovy.control.*
import
static
org.codehaus.groovy.syntax.Types.*


def
imports
=
new
ImportCustomizer().addStaticStars('java.lang.Math')
def
secure
=
new
SecureASTCustomizer()

                                                                  47
Secure AST customizer

 ...
 secure.with
{
   //
disallow
closure
creation
   closuresAllowed
=
false

   //
disallow
method
definitions
   methodDefinitionAllowed
=
false

 

   //
empty
white
list
=>
forbid
imports
   importsWhitelist
=
[]

   staticImportsWhitelist
=
[]
   //
only
allow
the
java.lang.Math.*
static
import
   staticStarImportsWhitelist
=
['java.lang.Math'
 ...


                                                      48
Secure AST customizer
...
   //
language
tokens
allowed
   tokensWhitelist
=
[
      PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,

      MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,

      COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,

      COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL
   ]


   //
types
allowed
to
be
used
(including
primitive
types)
   constantTypesClassesWhiteList
=
[
      Integer,
Float,
Long,
Double,
BigDecimal,

      Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE
   ]


   //
classes
who
are
allowed
to
be
receivers
of
method
calls
   receiversClassesWhiteList
=
[

      Math,
Integer,
Float,
Double,
Long,
BigDecimal
]
}
...

                                                                49
Secure AST customizer

• Ready to evaluate our arithmetic expressions!
    ...
    def
config
=
new
CompilerConfiguration()
    config.addCompilationCustomizers(imports,
secure)

    def
shell
=
new
GroovyShell(config)
    

    shell.evaluate
'cos(PI/3)'


• But the following would have failed:

            shell.evaluate
'System.exit(0)'


                                                        50
Slashy and dollar slashy strings

• Slashy strings are now multiline
  – particularly handy for multi-line regexs

• Dollar slashy string notation introduced
  – a multiline GString with different escaping rules
          def
(name,
date)
=
["Guillaume",
"May,
17th"]
          def
dollarSlashy
=
$/




          



Hello
$name,
today
we're
${date}
          



$
dollar‐sign




          



$$
dollar‐sign




          




backslash




          



/
slash




          


$/
slash
          /$


                                                          51
New GDK methods




                  52
New GDK methods

  //
count




                  52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  





                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  





                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]





                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1
  





                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1
  

  //
map
withDefault()




                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1
  

  //
map
withDefault()
  def
words
=
"one
two
two
three
three
three".split()



                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1
  

  //
map
withDefault()
  def
words
=
"one
two
two
three
three
three".split()
  def
freq
=
[:].withDefault
{
k
‐>
0
}


                                                          52
New GDK methods

  //
count
  assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5
  

  //
count
by
  assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
}
  assert
[(true):2,
(false):4]

  



==
'Groovy'.toList().countBy{
it
==
'o'
}
  

  //
min/max
for
maps
with
closures
  def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]

  assert
map.max
{
it.key.size()
}.key
==
'dddd'
  assert
map.min
{
it.value
}.value
==
1
  

  //
map
withDefault()
  def
words
=
"one
two
two
three
three
three".split()
  def
freq
=
[:].withDefault
{
k
‐>
0
}
  words.each
{
freq[it]
+=
1
}

                                                          52
(G)String to Enum coercion

       enum
Color
{




       



red,
green,
blue
       }





                              53
(G)String to Enum coercion

       enum
Color
{




       



red,
green,
blue
       }

       





                              53
(G)String to Enum coercion

       enum
Color
{




       



red,
green,
blue
       }

       

       //
coercion
with
as
       def
r
=
"red"
as
Color

       





                                 53
(G)String to Enum coercion

       enum
Color
{




       



red,
green,
blue
       }

       

       //
coercion
with
as
       def
r
=
"red"
as
Color

       

       //
implicit
coercion
       Color
b
=
"blue"

       





                                 53
(G)String to Enum coercion

       enum
Color
{




       



red,
green,
blue
       }

       

       //
coercion
with
as
       def
r
=
"red"
as
Color

       

       //
implicit
coercion
       Color
b
=
"blue"

       

       //
with
GStrings
too
       def
g
=
"${'green'}"
as
Color


                                       53
What’s
cooking
for 1.9?
Groovy 1.9 roadmap

• Java 7 alignements: Project Coin
  – binary literals
  – underscore in literals
  – multicatch
• JDK 7: InvokeDynamic

• Towards a more modular Groovy
• Rewritten Antlr 3 grammar (GSoC)
• Eclipse compiler to replace
  the joint compiler?

• What else? Your call!

                                     55
Groovy 1.9 roadmap

• Java 7 alignements: Project Coin
  – binary literals
  – underscore in literals
  – multicatch
• JDK 7: InvokeDynamic

• Towards a more modular Groovy
• Rewritten Antlr 3 grammar (GSoC)
• Eclipse compiler to replace
  the joint compiler?

• What else? Your call!

                                     55
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


                                                    56
Underscore in literals


• We can now 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



                                                        57
Multicatch


• One block for multiple exception caught
  – rather than duplicating the block


   try
{
   



/*
...
*/
   }
catch(IOException
|
NullPointerException
e)
{
   



/*
one
block
to
treat
2
exceptions
*/
   }




                                                     58
Summary




          ROCKS!
              59
Thank you!




                                 e
                            aforg pment
                    ume L Develo
             Guilla Groovy            om
             He ad of      e@ gmail.c
                    glaforg rge
              Email: @glafo
                      :
              Twitter




                                           60
Image credits
•   Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg
•   Bicycle: http://drunkcyclist.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=2131&g2_serialNumber=2
•   Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg
•   Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg
•   Cheating: http://fr.academic.ru/pictures/frwiki/67/Cheating.JPG
•   Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/
•   Oui nide iou: http://desencyclopedie.wikia.com/wiki/Fichier:Superdupont_we_need_you.jpg
•   Guitar: http://www.lelitteraire.com/IMG/breveon323.jpg
•   Trampoline: http://www.fitness-online.fr/images/trampoline-1-m.jpg
•   Curry: http://www.pot-a-epices.com/wp-content/uploads/2009/02/curry1.jpg
•   Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg




                                                                                                                            61

More Related Content

Similar to Groovy update - S2GForum London 2011 - Guillaume Laforge

Scrum and kanban
Scrum and kanbanScrum and kanban
Scrum and kanban
Agileee
 
qdoc.tips_oracle-dba-interview-questions.pdf
qdoc.tips_oracle-dba-interview-questions.pdfqdoc.tips_oracle-dba-interview-questions.pdf
qdoc.tips_oracle-dba-interview-questions.pdf
OsamaQahtan
 
Testing Cassandra Guarantees under Diverse Failure Modes with Jepsen
Testing Cassandra Guarantees under Diverse Failure Modes with JepsenTesting Cassandra Guarantees under Diverse Failure Modes with Jepsen
Testing Cassandra Guarantees under Diverse Failure Modes with Jepsen
jkni
 

Similar to Groovy update - S2GForum London 2011 - Guillaume Laforge (20)

Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011Groovy Update - Guillaume Laforge - Greach 2011
Groovy Update - Guillaume Laforge - Greach 2011
 
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - Spri...
 
Sangam 18 - Database Development: Return of the SQL Jedi
Sangam 18 - Database Development: Return of the SQL JediSangam 18 - Database Development: Return of the SQL Jedi
Sangam 18 - Database Development: Return of the SQL Jedi
 
Scrum and kanban
Scrum and kanbanScrum and kanban
Scrum and kanban
 
qdoc.tips_oracle-dba-interview-questions.pdf
qdoc.tips_oracle-dba-interview-questions.pdfqdoc.tips_oracle-dba-interview-questions.pdf
qdoc.tips_oracle-dba-interview-questions.pdf
 
The Ring programming language version 1.6 book - Part 8 of 189
The Ring programming language version 1.6 book - Part 8 of 189The Ring programming language version 1.6 book - Part 8 of 189
The Ring programming language version 1.6 book - Part 8 of 189
 
The Ring programming language version 1.7 book - Part 9 of 196
The Ring programming language version 1.7 book - Part 9 of 196The Ring programming language version 1.7 book - Part 9 of 196
The Ring programming language version 1.7 book - Part 9 of 196
 
9 cm604.13
9 cm604.139 cm604.13
9 cm604.13
 
DataStax: Testing Cassandra Guarantees Under Diverse Failure Modes With Jepsen
DataStax: Testing Cassandra Guarantees Under Diverse Failure Modes With JepsenDataStax: Testing Cassandra Guarantees Under Diverse Failure Modes With Jepsen
DataStax: Testing Cassandra Guarantees Under Diverse Failure Modes With Jepsen
 
Testing Cassandra Guarantees under Diverse Failure Modes with Jepsen
Testing Cassandra Guarantees under Diverse Failure Modes with JepsenTesting Cassandra Guarantees under Diverse Failure Modes with Jepsen
Testing Cassandra Guarantees under Diverse Failure Modes with Jepsen
 
Tiad - Docker: Automation for the rest of us
Tiad - Docker: Automation for the rest of usTiad - Docker: Automation for the rest of us
Tiad - Docker: Automation for the rest of us
 
Docker: automation for the rest of us
Docker: automation for the rest of usDocker: automation for the rest of us
Docker: automation for the rest of us
 
CakePHP - The Path to 2.0
CakePHP - The Path to 2.0CakePHP - The Path to 2.0
CakePHP - The Path to 2.0
 
Introducing Ansible
Introducing AnsibleIntroducing Ansible
Introducing Ansible
 
Head in the Clouds: Testing Infra as Code - Config Management 2020
Head in the Clouds: Testing Infra as Code - Config Management 2020Head in the Clouds: Testing Infra as Code - Config Management 2020
Head in the Clouds: Testing Infra as Code - Config Management 2020
 
OpenPOWER Application Optimization
OpenPOWER Application Optimization OpenPOWER Application Optimization
OpenPOWER Application Optimization
 
Know your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvmKnow your platform. 7 things every scala developer should know about jvm
Know your platform. 7 things every scala developer should know about jvm
 
The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202
 
Winning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test CycleWinning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test Cycle
 
CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013CoffeeScript - TechTalk 21/10/2013
CoffeeScript - TechTalk 21/10/2013
 

More from Guillaume Laforge

Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Guillaume Laforge
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
Guillaume Laforge
 
Cloud foundry intro with groovy
Cloud foundry intro with groovyCloud foundry intro with groovy
Cloud foundry intro with groovy
Guillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Guillaume Laforge
 
Gaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume LaforgeGaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume Laforge
Guillaume Laforge
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Guillaume Laforge
 

More from Guillaume Laforge (20)

Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013
 
Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013
 
Groovy 2 and beyond
Groovy 2 and beyondGroovy 2 and beyond
Groovy 2 and beyond
 
Groovy 2.0 webinar
Groovy 2.0 webinarGroovy 2.0 webinar
Groovy 2.0 webinar
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012
 
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012Groovy 1.8 and 2.0 at GR8Conf Europe 2012
Groovy 1.8 and 2.0 at GR8Conf Europe 2012
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
 
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
 
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
 
Cloud foundry intro with groovy
Cloud foundry intro with groovyCloud foundry intro with groovy
Cloud foundry intro with groovy
 
Groovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume LaforgeGroovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
 
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
 
Gaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume LaforgeGaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume Laforge
 
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGroovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
 
Gaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume LaforgeGaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume Laforge
 
Gaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume LaforgeGaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Recently uploaded (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 

Groovy update - S2GForum London 2011 - Guillaume Laforge

  • 1. Groovy Update What’s new in Groovy 1.8, and what’s cooking in 1.9! Guillaume Laforge Groovy Project Manager SpringSource / VMware
  • 2. Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • 3. Guillaume Laforge • Groovy Project Manager • JSR-241 Spec Lead • Head of Groovy Development at SpringSource / VMWare • Initiator of the Grails framework • Creator of the Gaelyk toolkit • Co-author of Groovy in Action • Speaker: JavaOne, QCon, JavaZone, Sun TechDays, Devoxx, The Spring Experience, SpringOne, JAX, Dynamic Language World, IJTC, and more... 2
  • 7. Groovy 1.7 185k FIRST MONTH AFTER RELEASE 3
  • 9. Groovy 1.7 177k SECOND MONTH AFTER RELEASE 3
  • 10. Groovy 1.7 k 3
  • 13. Agenda 5
  • 14. Agenda • What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous 5
  • 15. Agenda • What’s new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations – Miscelanous • What’s cooking for Groovy 1.9? – Continued runtime performance improvements – Alignments with JDK 7 • Project Coin (small language changes) • InvokeDynamic 5
  • 17. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6
  • 18. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println 6
  • 19. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 6
  • 20. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) 6
  • 21. Command chains expressions • A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println • Less dots, less parens allow you to – write more readable business rules – in almost plain English sentences • (or any language, of course) • Let’s have a look at some examples 6
  • 22. Command chains expressions 
turn
left

then
right
 7
  • 23. Command chains expressions Alternation of method names 
turn
left

then
right
 7
  • 24. Command chains expressions Alternation of method names 
turn
left

then
right
 and parameters (even named ones) 7
  • 25. Command chains expressions 
turn
left

then
right
 7
  • 26. Command chains expressions Equivalent to: 




(



).



(




) 
turn
left

then
right
 7
  • 27. LookM a! N op are ns, no do ts!
  • 28. Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours 9
  • 29. Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument 9
  • 30. Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument Named arguments 9
  • 31. Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument Named arguments Woud call: def
take(Map
m,
Quantity
q) 9
  • 32. Command chains expressions Now, even less punctuation! take
2.pills

of

chloroquinine

after

6.hours 10
  • 33. Command chains expressions Now, even less punctuation! 



(






).


(












).





(






) take
2.pills

of

chloroquinine

after

6.hours 10
  • 34. Command chains expressions //
environment
initialization Integer.metaClass.getPills
{
‐>
delegate
} Integer.metaClass.getHours
{
‐>
delegate
} 
 //
variable
injection def
chloroquinine
=
/*...*/ 
 { } //
implementing
the
DSL
logic def
take(n)
{ 



[of:
{
drug
‐> 







[after:
{
time
‐>
/*...*/
}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2.pills
of
chloroquinine
after
6.hours 11
  • 35. Command chains expressions take
2.pills

of

chloroquinine

after

6.hours 12
  • 36. Command chains expressions take
2.pills

of

chloroquinine

after

6.hours ... some dots remain ... 12
  • 37. Command chains expressions We could cheat a bit... take
2

pills
of

chloroquinine
6

hours
after 13
  • 38. Command chains expressions We could cheat a bit... 



(
).




(

).












(
).




(




) take
2

pills
of

chloroquinine
6

hours
after 13
  • 39. Cheating is playing with the language
  • 40. Command chains expressions Still doable without cheating though take
2

pills
of

chloroquinine
after

6
hours 15
  • 41. Command chains expressions Still doable without cheating though 



(
).




(

).












(




).
(




) take
2

pills
of

chloroquinine
after

6
hours 15
  • 42. Command chains expressions //
variable
injection def
(of,
after,
hours)
=
/*...*/ 
 //
implementing
the
DSL
logic { } def
take(n)
{ 



[pills:
{
of
‐> 







[chloroquinine:
{
after
‐> 











['6':
{
time
‐>
}] 







}] 



}] } //
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take
2
pills
of
chloroquinine
after
6
hours 16
  • 44. Command chains expressions //
methods
with
multiple
arguments
(commas) 17
  • 45. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 17
  • 46. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation 17
  • 47. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 17
  • 48. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures 17
  • 49. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 17
  • 50. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens 17
  • 51. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names 17
  • 52. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms 17
  • 53. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • 54. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • 55. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • 56. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • 57. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 17
  • 58. Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor 



(





).



(










).


(





) //
leverage
named‐args
as
punctuation check
that:
margarita

tastes
good 




(














).





(



) //
closure
parameters
for
new
control
structures given
{}

when
{}

then
{} 




(

).



(

).



(

) //
zero‐arg
methods
require
parens select
all

unique()
from
names 





(


).







.



(




) //
possible
with
an
odd
number
of
terms take
3

cookies 



(
). 17
  • 59. Runtime performance improvements • Significant runtime improvements for primitive int operations – classical Fibonacci example x13 faster! – almost as fast as Java • Some direct method calls on this • But there’s more to come! – in particular for all the primitive types 18
  • 60. GPars bundled • GPars is bundled in the Groovy distribution • GPars covers a wide range of parallel and concurrent paradigms – actors, fork/join, dataflow, agents, STM... 19
  • 61. Closure enhancements • Closure annotation parameters • Some more functional flavor – composition – trampoline – memoization • Currying improvements 20
  • 62. Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface
Invariant
{



 



Class
value()
//
a
closure
class } 
 { @Invariant({
number
>=
0
}) class
Distance
{



 



float
number



 



String
unit }
 
 def
d
=
new
Distance(number:
10,
unit:
"meters")
 def
anno
=
Distance.getAnnotation(Invariant) def
check
=
anno.value().newInstance(d,
d) assert
check(d) 21
  • 63. Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface
Invariant
{



 



Class
value()
//
a
closure
class } 
 { @Invariant({
number
>=
0
}) class
Distance
{



 



float
number



 an’s G Cont racts 



String
unit P oor-m }
 
 def
d
=
new
Distance(number:
10,
unit:
"meters")
 def
anno
=
Distance.getAnnotation(Invariant) def
check
=
anno.value().newInstance(d,
d) assert
check(d) 21
  • 64. Closure composition def
plus2

=
{
it
+
2
} def
times3
=
{
it
*
3
}
 
 { def
times3plus2
=
plus2
<<
times3 assert
times3plus2(3)
==
11 assert
times3plus2(4)
==
plus2(times3(4))
 
 { def
plus2times3
=
times3
<<
plus2 assert
plus2times3(3)
==
15 assert
plus2times3(5)
==
times3(plus2(5))
 
 //
reverse
composition { assert
times3plus2(3)
==
(times3
>>
plus2)(3) 22
  • 66. Closure trampoline def
factorial factorial
=
{
int
n,
BigInteger
accu
=
1G
‐>
 
 



if
(n
<
2)
return
accu




 



factorial.trampoline(n
‐
1,
n
*
accu) }.trampoline() 
 assert
factorial(1)



==
1 assert
factorial(3)



==
1
*
2
*
3 assert
factorial(1000)
==
402387260... 23
  • 70. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately 24
  • 71. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms 24
  • 72. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 24
  • 73. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 24
  • 74. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached 24
  • 75. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 24
  • 76. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 24
  • 77. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached 24
  • 78. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 24
  • 79. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 //
between
10
and
20
invocations
cached 24
  • 80. Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately assert
plus(2,
2)
==
4
//
after
1000ms assert
plus(2,
2)
==
4
//
return
immediately

 
 //
at
least
10
invocations
cached def
plusAtLeast
=
{
...
}.memoizeAtLeast(10) 
 //
at
most
10
invocations
cached def
plusAtMost
=
{
...
}.memoizeAtMost(10)
 //
between
10
and
20
invocations
cached def
plusAtLeast
=
{
...
}.memoizeBetween(10,
20) 24
  • 82. Currying improvements //
right
currying def
divide
=
{
a,
b
‐>
a
/
b
} def
halver
=
divide.rcurry(2) assert
halver(8)
==
4

 
 25
  • 83. Currying improvements //
right
currying def
divide
=
{
a,
b
‐>
a
/
b
} def
halver
=
divide.rcurry(2) assert
halver(8)
==
4

 
 //
currying
n‐th
parameter def
joinWithSeparator
=
 



{
one,
sep,
two
‐>
one
+
sep
+
two
} def
joinWithComma
=
 



joinWithSeparator.ncurry(1,
',
') assert
joinWithComma('a',
'b')
==
'a,
b' 25
  • 84. Builtin JSON support • Consuming • Producing • Pretty-printing 26
  • 86. Builtin JSON support import
groovy.json.*
 
 def
json
=
new
JsonBuilder()
 
 json.person
{



 



name
"Guillaume" 



age
33



 



pets
"Hector",
"Felix" }
 println
json.toString() 28
  • 87. Builtin JSON support import
groovy.json.*
 
 println
JsonOutput.prettyPrint( 



'''{"person":{"name":"Guillaume","age":33,'''
+
 



'''"pets":["Hector","Felix"]}}''') 
 29
  • 88. Builtin JSON support import
groovy.json.*
 
 println
JsonOutput.prettyPrint( 



'''{"person":{"name":"Guillaume","age":33,'''
+
 



'''"pets":["Hector","Felix"]}}''') 
 {



 



"person":
{







 







"name":
"Guillaume",


 
 







"age":
33,







 







"pets":
[











 











"Hector",









 
 











"Felix"







 







]



 



} } 29
  • 89. New AST transformations • @Log • @Canonical – @ToString, • @Field – @EqualsAndHashCode, – @TupleConstructor • @AutoClone • @InheritConstructor • @AutoExternalizable • @WithReadLock • Controlling the execution of your code • @WithWriteLock – @ThreadInterrupt, – @TimedInterrupt, • @ListenerList – @ConditionalInterrupt 30
  • 90. @Log • Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j • Possible to implement your own strategy import
groovy.util.logging.*
 
 @Log class
Car
{



 



Car()
{







 







log.info
'Car
constructed'

 
 



} }
 
 def
c
=
new
Car() 31
  • 91. @Log • Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j • Possible to implement your own strategy import
groovy.util.logging.*
 
 @Log class
Car
{



 Guarded 



Car()
{







 w/ an if 







log.info
'Car
constructed'

 
 



} }
 
 def
c
=
new
Car() 31
  • 92. @Field • Surprising scoping rules in scripts – variables are local to the run() method – variables aren’t visible in methods • although visually the variable is in a surrounding scope • @Field creates a field in the script class @Field
List
awe
=
[1,
2,
3] def
awesum()
{
awe.sum()
} assert
awesum()
==
6 32
  • 93. Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? 33
  • 94. Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33
  • 95. Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 33
  • 96. Controlling code execution • Your application may run user’s code – what if the code runs in infinite loops or for too long? – what if the code consumes too many resources? • 3 new transforms at your rescue – @ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted – @TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected – @ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code • Also see compilation customizers later on 33
  • 97. @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ 



//
eat
lots
of
CPU } 34
  • 98. @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ { 



if
(Thread.currentThread.isInterrupted()) 







throw
new
InterruptedException() } 



//
eat
lots
of
CPU } 34
  • 99. @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ { 



if
(Thread.currentThread.isInterrupted()) 







throw
new
InterruptedException() } 



//
eat
lots
of
CPU } • Two optional annotation parameters available – checkOnMethodStart (true by default) – applyToAllClasses (true by default) 34
  • 100. @TimedInterrupt @TimedInterrupt(10) import
groovy.transform.TimedInterrupt
 
 while
(true)
{ 



//
eat
lots
of
CPU } • InterruptedException thrown when checks indicate code ran longer than desired • Optional annotation parameters available – same as @ThreadInterrupt – value: for an amount of time duration – unit: for the time duration unit (TimeUnit.SECONDS) 35
  • 101. @ConditionalInterrupt • Specify your own condition to be inserted at the start of method and closure bodies – check for available resources, number of times run, etc. • Leverages closure annotation parameters from Groovy 1.8 @ConditionalInterrupt({
counter++
>
2
}) import
groovy.transform.ConditionalInterrupt import
groovy.transform.Field
 
 @Field
int
counter
=
0
 100.times
{



 



println
'executing
script
method...' } 36
  • 102. @ToString • Provides a default toString() method to your types • Available annotation options – includeNames, includeFields, includeSuper, excludes import
groovy.transform.ToString
 
 @ToString class
Person
{



 



String
name



 



int
age }
 
 println
new
Person(name:
'Pete',
age:
15) //
=>
Person(Pete,
15) 37
  • 103. @EqualsAndHashCode • Provides default implementations for equals() and hashCode() methods import
groovy.transform.EqualsAndHashCode
 
 @EqualsAndHashCode class
Coord
{



 



int
x,
y }
 
 def
c1
=
new
Coord(x:
20,
y:
5) def
c2
=
new
Coord(x:
20,
y:
5)
 
 assert
c1
==
c2 assert
c1.hashCode()
==
c2.hashCode() 38
  • 104. @TupleConstructor • Provides a «classical» constructor with all properties • Several annotation parameter options available import
groovy.transform.TupleConstructor
 
 @TupleConstructor
 class
Person
{



 



String
name



 



int
age }
 
 def
m
=
new
Person('Marion',
3)





 
 assert
m.name
==
'Marion' assert
m.age

==
3 39
  • 105. @Canonical • One annotation to rule them all! – @Canonical mixes together • @ToString • @EqualsAndHashCode • @TupleConstructor • You can customize behavior by combining @Canonical and one of the other annotations 40
  • 106. @InheritConstructor • Classes like Exception are painful when extended, as all the base constructors should be replicated class
CustomException
extends
Exception
{ 



CustomException()























{
super()






} 



CustomException(String
msg)













{
super(msg)



} 



CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
} 



CustomException(Throwable
t)












{
super(t)





} } 41
  • 107. @InheritConstructor • Classes like Exception are painful when extended, as all the base constructors should be replicated import
groovy.transform.* @InheritConstructors class
CustomException
extends
Exception
{ 



CustomException()























{
super()






} 



CustomException(String
msg)













{
super(msg)



} 



CustomException(String
msg,
Throwable
t)
{
super(msg,
t)
} 



CustomException(Throwable
t)












{
super(t)





} } 41
  • 108. @WithReadLock, @WithWriteLock import
groovy.transform.*
 
 class
ResourceProvider
{



 



private
final
Map<String,
String>
data
=
new
HashMap<>() 
 



@WithReadLock



 



String
getResource(String
key)
{







 







return
data.get(key)



 



}




 
 



@WithWriteLock



 



void
refresh()
{







 







//reload
the
resources
into
memory



 



} } 42
  • 109. @WithReadLock, @WithWriteLock import
groovy.transform.*
 
 class
ResourceProvider
{



 



private
final
Map<String,
String>
data
=
new
HashMap<>() 
 { 



@WithReadLock



 



String
getResource(String
key)
{







 







return
data.get(key)



 



}




 
 { 



@WithWriteLock



 



void
refresh()
{







 







//reload
the
resources
into
memory



 



} } 42
  • 110. Miscelanous • Compilation customizers • Java 7 diamond operator • Slashy and dollar slashy strings • New GDK methods • (G)String to Enum coercion 43
  • 111. Compilation customizers • Ability to apply some customization to the Groovy compilation process • Three available customizers – ImportCustomizer – SecureASTCustomizer – ASTTransformationCustomizer • But you can implement your own 44
  • 113. Applying an AST transformation def
configuration
=
new
CompilerConfiguration() configuration.addCompilationCustomizers( 



new
ASTTransformationCustomizer(Log))
 
 new
GroovyShell(configuration).evaluate(""" 



class
Car
{







 







Car()
{











 











log.info
'Car
constructed'







 







}



 



}




 



log.info
'Constructing
a
car'



 



def
c
=
new
Car() """) 46
  • 114. Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions • Let’s setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizer import
org.codehaus.groovy.control.customizers.* import
org.codehaus.groovy.control.* import
static
org.codehaus.groovy.syntax.Types.* 
 def
imports
=
new
ImportCustomizer().addStaticStars('java.lang.Math') def
secure
=
new
SecureASTCustomizer() 47
  • 115. Secure AST customizer ... secure.with
{ //
disallow
closure
creation closuresAllowed
=
false
 //
disallow
method
definitions methodDefinitionAllowed
=
false
 
 //
empty
white
list
=>
forbid
imports importsWhitelist
=
[]
 staticImportsWhitelist
=
[] //
only
allow
the
java.lang.Math.*
static
import staticStarImportsWhitelist
=
['java.lang.Math' ... 48
  • 116. Secure AST customizer ... //
language
tokens
allowed tokensWhitelist
=
[ PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,
 MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,
 COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,
 COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL ] 
 //
types
allowed
to
be
used
(including
primitive
types) constantTypesClassesWhiteList
=
[ Integer,
Float,
Long,
Double,
BigDecimal,
 Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE ] 
 //
classes
who
are
allowed
to
be
receivers
of
method
calls receiversClassesWhiteList
=
[
 Math,
Integer,
Float,
Double,
Long,
BigDecimal
] } ... 49
  • 117. Secure AST customizer • Ready to evaluate our arithmetic expressions! ... def
config
=
new
CompilerConfiguration() config.addCompilationCustomizers(imports,
secure) def
shell
=
new
GroovyShell(config) 
 shell.evaluate
'cos(PI/3)' • But the following would have failed: shell.evaluate
'System.exit(0)' 50
  • 118. Slashy and dollar slashy strings • Slashy strings are now multiline – particularly handy for multi-line regexs • Dollar slashy string notation introduced – a multiline GString with different escaping rules def
(name,
date)
=
["Guillaume",
"May,
17th"] def
dollarSlashy
=
$/



 



Hello
$name,
today
we're
${date} 



$
dollar‐sign



 



$$
dollar‐sign



 




backslash



 



/
slash



 


$/
slash /$
 51
  • 120. New GDK methods //
count 52
  • 121. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 52
  • 122. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 52
  • 123. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by 52
  • 124. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} 52
  • 125. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 52
  • 126. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 52
  • 127. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures 52
  • 128. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 52
  • 129. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' 52
  • 130. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 52
  • 131. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 
 52
  • 132. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() 52
  • 133. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() 52
  • 134. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() def
freq
=
[:].withDefault
{
k
‐>
0
} 52
  • 135. New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by assert
[0:2,
1:3]
==
[1,2,3,4,5].countBy{
it
%
2
} assert
[(true):2,
(false):4]
 



==
'Groovy'.toList().countBy{
it
==
'o'
} 
 //
min/max
for
maps
with
closures def
map
=
[a:
1,
bbb:
4,
cc:
5,
dddd:
2]
 assert
map.max
{
it.key.size()
}.key
==
'dddd' assert
map.min
{
it.value
}.value
==
1 
 //
map
withDefault() def
words
=
"one
two
two
three
three
three".split() def
freq
=
[:].withDefault
{
k
‐>
0
} words.each
{
freq[it]
+=
1
} 52
  • 136. (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 53
  • 137. (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 53
  • 138. (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 53
  • 139. (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
 
 53
  • 140. (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
 
 //
with
GStrings
too def
g
=
"${'green'}"
as
Color 53
  • 142. Groovy 1.9 roadmap • Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch • JDK 7: InvokeDynamic • Towards a more modular Groovy • Rewritten Antlr 3 grammar (GSoC) • Eclipse compiler to replace the joint compiler? • What else? Your call! 55
  • 143. Groovy 1.9 roadmap • Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch • JDK 7: InvokeDynamic • Towards a more modular Groovy • Rewritten Antlr 3 grammar (GSoC) • Eclipse compiler to replace the joint compiler? • What else? Your call! 55
  • 144. 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 56
  • 145. Underscore in literals • We can now 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 57
  • 146. Multicatch • One block for multiple exception caught – rather than duplicating the block try
{ 



/*
...
*/ }
catch(IOException
|
NullPointerException
e)
{ 



/*
one
block
to
treat
2
exceptions
*/ } 58
  • 147. Summary ROCKS! 59
  • 148. Thank you! e aforg pment ume L Develo Guilla Groovy om He ad of e@ gmail.c glaforg rge Email: @glafo : Twitter 60
  • 149. Image credits • Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg • Bicycle: http://drunkcyclist.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=2131&g2_serialNumber=2 • Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg • Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg • Cheating: http://fr.academic.ru/pictures/frwiki/67/Cheating.JPG • Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/ • Oui nide iou: http://desencyclopedie.wikia.com/wiki/Fichier:Superdupont_we_need_you.jpg • Guitar: http://www.lelitteraire.com/IMG/breveon323.jpg • Trampoline: http://www.fitness-online.fr/images/trampoline-1-m.jpg • Curry: http://www.pot-a-epices.com/wp-content/uploads/2009/02/curry1.jpg • Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg 61

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n
  167. \n