• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - SpringOne2GX 2011
 

Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - SpringOne2GX 2011

on

  • 3,401 views

All the novelties of Groovy 1.8, and the work in progress of the new features in Groovy 1.9 and beyond.

All the novelties of Groovy 1.8, and the work in progress of the new features in Groovy 1.9 and beyond.

Statistics

Views

Total Views
3,401
Views on SlideShare
3,067
Embed Views
334

Actions

Likes
4
Downloads
69
Comments
0

4 Embeds 334

http://glaforge.appspot.com 312
http://feeds.feedburner.com 16
http://a0.twimg.com 5
http://us-w1.rockmelt.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

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

Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - SpringOne2GX 2011 Groovy Update, what's new in Groovy 1.8 and beyond - Guillaume Laforge - SpringOne2GX 2011 Presentation Transcript

  • Whatʼs new in Groovy 1.8 and beyond?Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMwareTwitter: @glaforgeBlog: http://glaforge.appspot.com© 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
  • Guillaume Laforge• Groovy Project Manager at VMware • Initiator of the Grails framework • Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaking worldwide w/ a French accent• Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge2 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Guillaume Laforge• Groovy Project Manager at VMware • Initiator of the Grails framework • Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaking worldwide w/ a French accent• Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge2 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.73 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.71853 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7185k3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7185k FIRST MONTH AFTER RELEASE3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7 k3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7177k SECOND MONTH AFTER RELEASE3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7 k3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.7362k USERS?3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • ?TIP OFTHEICEBERG
  • Guesstimate 1/2 Users5 Million @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Agenda6 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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 transformations6 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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• Whatʼs cooking for Groovy 1.9? – Continued runtime performance improvements – Alignments with JDK 7 • Project Coin (small language changes)6 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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 examples7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions 
turn
left

then
right
8 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Alternation of method names 
turn
left

then
right
8 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Alternation of method names 
turn
left

then
right
 and parameters (even named ones)8 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions 
turn
left

then
right
8 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Equivalent to: 




(



).



(




) 
turn
left

then
right
8 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • LookM a!N op are ns,no do ts!
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours10 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument10 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Before... we used to do... take
2.pills,
of:
chloroquinine,
after:
6.hours Normal argument Named arguments10 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)10 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Now, even less punctuation! take
2.pills

of

chloroquinine

after

6.hours11 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Now, even less punctuation! 



(






).


(












).





(






) take
2.pills

of

chloroquinine

after

6.hours11 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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.hours12 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions take
2.pills

of

chloroquinine

after

6.hours13 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions take
2.pills

of

chloroquinine

after

6.hours ... some dots remain ...13 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Yes, we can... get rid of them :-) take
2

pills
of

chloroquinine

after

6
hours14 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions Yes, we can... get rid of them :-) 



(
).




(

).













(




).
(




) take
2

pills
of

chloroquinine

after

6
hours14 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
hours15 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Command chains expressions @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • Command chains expressions //
methods
with
multiple
arguments
(commas) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • Command chains expressions //
methods
with
multiple
arguments
(commas) take
coffee

with
sugar,
milk

and
liquor //
leverage
named‐args
as
punctuation @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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
{} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • 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 



(
). @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  • Runtime performance improvements• Significant runtime improvements for primitive type operations – classical Fibonacci example x13 faster! – almost as fast as Java• Some direct method calls on this17 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • GPars bundled• GPars is bundled in the Groovy distribution• GPars covers a wide range of parallel and concurrent paradigms – actors, fork/join, map/filter/reduce, dataflow, agents, STM – parallel arrays, executors, and more...• Don’t miss the following presentations on GPars – Paul King — Thursday, 12:45 - 2:15PM • Groovy & Concurrency with GPars – Venkat Subramaniam — Friday, 8:30 - 10:00AM18 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Closure enhancements• Closure annotation parameters• Some more functional flavor – composition – trampoline – memoization• Currying improvements19 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)20 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)20 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 21
  • Closure trampoline22 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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...22 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Closure memoization23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize()23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Closure memoization def
plus
=
{
a,
b
‐>
sleep
1000;
a
+
b
}.memoize() assert
plus(1,
2)
==
3
//
after
1000ms assert
plus(1,
2)
==
3
//
return
immediately23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
1000ms23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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

23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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

 
23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
cached23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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) 
23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
cached23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)
23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
cached23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)23 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Currying improvements24 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Currying improvements //
right
currying def
divide
=
{
a,
b
‐>
a
/
b
} def
halver
=
divide.rcurry(2) assert
halver(8)
==
4

 
24 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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,
b24 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Builtin JSON support• Consuming• Producing• Pretty-printing25 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
}26 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Builtin JSON support import
groovy.json.*
 
 def
json
=
new
JsonBuilder()
 
 json.person
{



 



name
"Guillaume" 



age
33



 



pets
"Hector",
"Felix" }
 println
json.toString()27 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Builtin JSON support import
groovy.json.*
 
 println
JsonOutput.prettyPrint( 



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



"pets":["Hector","Felix"]}}) 
28 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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"







 







]



 



} }28 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New AST transformations• @Log – @ConditionalInterrupt• @Field • @Canonical – @ToString, – @EqualsAndHashCode,• @AutoClone – @TupleConstructor• @AutoExternalizable • @InheritConstructor• Controlling the execution of your code – @ThreadInterrupt, • @WithReadLock – @TimedInterrupt, • @WithWriteLock29 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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()30 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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()30 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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()
==
631 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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?32 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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 code32 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ 



//
eat
lots
of
CPU } 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @ThreadInterrupt @ThreadInterrupt import
groovy.transform.ThreadInterrupt
 
 while
(true)
{ { 



if
(Thread.currentThread.isInterrupted()) 







throw
new
InterruptedException() } 



//
eat
lots
of
CPU } 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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) 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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 duration34 – unit: for the time duration unit (TimeUnit.SECONDS) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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... }35 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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)36 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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()37 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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

==
338 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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 annotations39 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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)





} }40 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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)





} }40 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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



 



} }41 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • @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



 



} }41 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Miscelanous• Compilation customizers• Java 7 diamond operator• Slashy and dollar slashy strings• New GDK methods• (G)String to Enum coercion42 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Compilation customizers• Ability to apply some customization to the Groovy compilation process• Three available customizers – ImportCustomizer – SecureASTCustomizer – ASTTransformationCustomizer• But you can implement your own43 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
")44 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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() """)45 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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()46 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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 ...47 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
] } ...48 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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)49 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Slashy and dollar slashy strings• Slashy strings are now multiline – particularly handy for multi-line regexs• Dollar slashy string notation introduced def
(name,
date)
=
["Guillaume",
"Oct,
26th"] def
dollarSlashy
=
$/



 



Hello
$name,
today
were
${date} 



$
dollar‐sign



 



$$
dollar‐sign



 




backslash



 



/
slash



 


$/
slash /$
50 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New GDK methods51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New GDK methods //
count51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
551 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • New GDK methods //
count assert
[2,4,2,1,3,5,2,4,3].count
{
it
%
2
==
0
}
==
5 
 //
count
by51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
}51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
}51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
} 
51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
closures51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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]
51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
==
dddd51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
==
151 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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 
51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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()51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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()51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
}51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • 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
}51 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (G)String to Enum coercion enum
Color
{



 



red,
green,
blue }
 
 //
coercion
with
as def
r
=
"red"
as
Color
 
 //
implicit
coercion Color
b
=
"blue"
 
52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (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
too52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • (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
Color52 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Customizing the Groovysh prompt53 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Launching remote scripts• With the Groovy command, you can launch remote scripts >
groovy
http://groovyconsole.appspot.com/raw/110001• Be careful to what you’re executing :-)54 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • What’scookingfor 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• Static type checking and compilation• Miscelanous• What else? Your call!56 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy 1.9 roadmap• Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch• JDK 7: InvokeDynamic• Towards a more modular Groovy• Static type checking and compilation• Miscelanous• What else? Your call!56 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Java 7 / JDK 7• Project Coin and InvokeDynamic57 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Binary literals• We had decimal, octal and hexadecimal notations for number literals int
x
=
0b10101111 assert
x
==
175 
 byte
aByte
=
0b00100001 assert
aByte
==
33 
 int
anInt
=
0b1010000101000101 assert
anInt
==
4128558 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Underscore in literals• Now we can also add underscores in number literals for more readability long
creditCardNumber
=
1234_5678_9012_3456L long
socialSecurityNumbers
=
999_99_9999L float
monetaryAmount
=
12_345_132.12 long
hexBytes
=
0xFF_EC_DE_5E long
hexWords
=
0xFFEC_DE5E long
maxLong
=
0x7fff_ffff_ffff_ffffL long
alsoMaxLong
=
9_223_372_036_854_775_807L long
bytes
=
0b11010010_01101001_10010100_1001001059 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Multicatch• One block for multiple exception caught – rather than duplicating the block try
{ 



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



/*
one
block
to
treat
2
exceptions
*/ }60 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • InvokeDynamic• Groovy 1.9 will support JDK 7ʼs invokeDynamic – an «indy» branch started recently – compiler will have a flag for compiling against JDK 7• Benefits – more runtime performance! – in the long run, will allow us to get rid of code! • call site caching, thanks to MethodHandles • metaclass registry, thanks to ClassValues • will let the JIT inline calls more easily61 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Groovy Modularity• Groovy’s «all» JAR weighs in at 4MB• Nobody needs everything – Template engine, Ant scripting, Swing UI building...• Provide a smaller core – and several smaller JARs per feature• Paul King covers Groovy modularisation – Wednesday, 12:45-2:15PM62 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Static Type Checking• Goal: make the Groovy compiler «grumpy»! – and throw compilation errors (not at runtime)• Not everybody needs dynamic features all the time – think Java libraries scripting• Grumpy should... – tell you about your method or variable typos – complain if you call methods that don’t exist – shout on assignments of wrong types – infer the types of your variables – figure out GDK methods63 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • A typo in your variable or method names import
groovy.transform.StaticTypes 
 void
method()
{} 
 @TypeChecked
test()
{ 



//
Cannot
find
matching
method
metthhoood() 



metthhoood() 
 



def
name
=
"Guillaume" 



//
variable
naamme
is
undeclared 



println
naamme }64 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • A typo in your variable or method names import
groovy.transform.StaticTypes 
 void
method()
{} 
 @TypeChecked
test()
{ 



//
Cannot
find
matching
method
metthhoood() 



metthhoood() 
 



def
name
=
"Guillaume" 



//
variable
naamme
is
undeclared Compilation 



println
naamme errors! }64 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Complain on wrong assignments //
cannot
assign
value
of
type...
to
variable... int
x
=
new
Object() Set
set
=
new
Object() 
 def
o
=
new
Object() int
x
=
o 
 String[]
strings
=
[a,b,c] int
str
=
strings[0] 
 //
cannot
find
matching
method
plus() int
i
=
0 i
+=
165 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Complain on wrong assignments //
cannot
assign
value
of
type...
to
variable... int
x
=
new
Object() Set
set
=
new
Object() Compilation 
 errors! def
o
=
new
Object() int
x
=
o 
 String[]
strings
=
[a,b,c] int
str
=
strings[0] 
 //
cannot
find
matching
method
plus() int
i
=
0 i
+=
165 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Complain on wrong return types String
method()
{
String
} //
cannot
assign
value
of
type
String... int
x
=
method() //
checks
if/else
branch
return
values int
method()
{ 



if
(true)
{
String
} 



else
{
42
} } //
works
for
switch/case
&
try/catch/finally 
 //
transparent
toString()
implied String
greeting(String
name)
{ 



def
sb
=
new
StringBuilder() 



sb
<<
"Hi"
<<
name }66 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Complain on wrong return types String
method()
{
String
} //
cannot
assign
value
of
type
String... int
x
=
method() Compilation errors! //
checks
if/else
branch
return
values int
method()
{ 



if
(true)
{
String
} 



else
{
42
} } //
works
for
switch/case
&
try/catch/finally 
 //
transparent
toString()
implied String
greeting(String
name)
{ 



def
sb
=
new
StringBuilder() 



sb
<<
"Hi"
<<
name }66 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Type inference @TypeChecked
test()
{ 



def
name
=
"

Guillaume

" 
 



//
String
type
infered
(even
inside
GString) 



println
"NAME
=
${name.toUpperCase()}"
 
 



//
Groovy
GDK
method
support 



//
(GDK
operator
overloading
too) 



println
name.trim() 
 



int[]
numbers
=
[1,
2,
3] 



//
Element
n
is
an
int 



for
(int
n
in
numbers)
{ 







println
n 



} }67 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Staticly checked method & dynamic method @TypeChecked String
greeting(String
name)
{ 



//
call
method
with
dynamic
behavior 



//
but
with
proper
signature 



generateMarkup(name.toUpperCase()) } 
 //
usual
dynamic
behavior String
generateMarkup(String
name)
{ 



def
sw
=
new
StringWriter() 



new
MarkupBuilder(sw).html
{ 







body
{ 











div
name 







} 



} 



sw.toString() }68 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Bytecode viewer• Groovy Console’s bytecode viewer from the AST browser window – select class generation phase – select a class node69 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Disable Global AST transformations //
witout
a
specific
configuration,
the
AST
builder
works def
shell
=
new
GroovyShell() shell.evaluate(script)
//
passes def
config
=
new
CompilerConfiguration() config.disabledGlobalASTTransformations
= 



[org.codehaus.groovy.ast.builder.AstBuilderTransformation] def
script
=
 



import
org.codehaus.groovy.ast.builder.AstBuilder 



new
AstBuilder().buildFromCode
{
"Hello"
} 
 //
now
with
the
configuration
in
place, //
the
AST
builder
transform
is
not
applied shell
=
new
GroovyShell(config)
//
<‐‐
with
the
configuration shouldFail
{ 



shell.evaluate(script)
//
fails }70 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Summary71 @glaforge — http://glaforge.appspot.com — ROCKS! http://gplus.to/glaforge
  • Thank you! e L aforg pment aume vy Develo Guill Groo m Hea d of g mail.co aforge@ mail: gl glaforge e E @ o /glaforg T witter : http://gplus.t Go ogle+:72 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
  • Q&A — Got questions, Really?73 © 2011 SpringOne 2GX 2011. All rights reserved. Do not distribute without permission.
  • 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• 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• Caution: http://www.jeunes-epinay-sur-seine.fr/wp-content/uploads/2010/11/caution-colocation.jpg• Grumpy: http://mafeuilledechou.fr/__oneclick_uploads/2010/05/grumpy.jpg• Modularity: http://php.jglobal.com/blog/wp-content/uploads/2009/11/modularity.jpg• Agenda: http://www.plombiereslesbains.fr/images/stories/agenda.jpg• Java 7: http://geeknizer.com/wp-content/uploads/java7.jpg• WIP: http://www.connetport.com/wp-content/uploads/Work_in_progress.svg_.png• Grumpy 2: http://grumpy.division-par-zero.fr/wp-content/images/grumpy.jpg•74 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge