Groovy Update - Guillaume Laforge - Greach 2011
-
Upload
guillaume-laforge -
Category
Technology
-
view
1.756 -
download
1
description
Transcript of Groovy Update - Guillaume Laforge - Greach 2011
Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMware
Twitter: @glaforgeBlog: http://glaforge.appspot.comGoogle+: http://gplus.to/glaforge
Whatʼs new in Groovy 1.8 and beyond?
@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/glaforge
2
@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/glaforge
2
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
1853
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
185k3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
185kFIRST MONTH AFTER RELEASE
3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
k3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
k177SECOND MONTH AFTER RELEASE
3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
k3
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Groovy 1.7
k362USERS?
3
TIP OF THEICEBERG?
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
1/2Million U
sers
Guesstimate
5
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Agenda
6
@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
6
@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)• Static type checking• InvokeDynamic
6
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
7
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
• A grammar improvement allowing you todrop dots & parens when chaining method calls– an extended version of top-level statements like println
7
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
• A grammar improvement allowing you todrop dots & parens when chaining method calls– an extended version of top-level statements like println
7
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
• A grammar improvement allowing you todrop 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 todrop 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 todrop 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
7
@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
turn left then right
Alternation of method names
8
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
turn left then right
Alternation of method names
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
turn left then right ( ). ( )
Equivalent to:
8
Look Ma!No parens, no dots!
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills, of: chloroquinine, after: 6.hours
Before... we used to do...
10
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills, of: chloroquinine, after: 6.hours
Before... we used to do...
Normal argument
10
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills, of: chloroquinine, after: 6.hours
Before... we used to do...
Normal argument Named arguments
10
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills, of: chloroquinine, after: 6.hours
Before... we used to do...
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
take 2.pills of chloroquinine after 6.hours
Now, even less punctuation!
11
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills of chloroquinine after 6.hours
Now, even less punctuation!
( ). ( ). ( )
11
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// environment initializationInteger.metaClass.getPills { ‐> delegate }Integer.metaClass.getHours { ‐> delegate } // variable injectiondef chloroquinine = /*...*/ // implementing the DSL logicdef take(n) { [of: { drug ‐> [after: { time ‐> /*...*/ }] }]}
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐take 2.pills of chloroquinine after 6.hours
{ }12
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2.pills of chloroquinine after 6.hours
13
@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
take 2 pills of chloroquinine after 6 hours
Yes, we can... get rid of them :-)
14
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
take 2 pills of chloroquinine after 6 hours
Yes, we can... get rid of them :-)
( ). ( ). ( ). ( )
14
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// variable injectiondef (of, after, hours) = /*...*/ // implementing the DSL logicdef take(n) { [pills: { of ‐> [chloroquinine: { after ‐> ['6': { time ‐> }] }] }]}
// ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐take 2 pills of chloroquinine after 6 hours
{ }15
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuation
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structures
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parens
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of terms
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
( ). ( ). ( )
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
( ). ( ). ( )
( ). ( )
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
( ). ( ). ( )
( ). ( )
( ). ( ). ( )
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
( ). ( ). ( )
( ). ( )
( ). ( ). ( )
( ). . ( )
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Command chains expressions
// methods with multiple arguments (commas)take coffee with sugar, milk and liquor
// leverage named‐args as punctuationcheck that: margarita tastes good
// closure parameters for new control structuresgiven {} when {} then {}
// zero‐arg methods require parensselect all unique() from names
// possible with an odd number of termstake 3 cookies
( ). ( ). ( )
( ). ( )
( ). ( ). ( )
( ). . ( )
( ).
16
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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 this
17
@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...
18
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure enhancements
• Closure annotation parameters
• Some more functional flavor– composition– trampoline– memoization
• Currying improvements
19
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure annotation parameters
20
@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)
{
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure annotation parameters
20
@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)
{Poor-man’s GContracts
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure composition
21
def plus2 = { it + 2 }def times3 = { it * 3 } def times3plus2 = plus2 << times3assert times3plus2(3) == 11assert times3plus2(4) == plus2(times3(4)) def plus2times3 = times3 << plus2assert plus2times3(3) == 15assert plus2times3(5) == times3(plus2(5)) // reverse compositionassert times3plus2(3) == (times3 >> plus2)(3)
{
{
{
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure trampoline
22
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure trampoline
22
def factorial
factorial = { int n, BigInteger accu = 1G ‐> if (n < 2) return accu factorial.trampoline(n ‐ 1, n * accu)}.trampoline() assert factorial(1) == 1assert factorial(3) == 1 * 2 * 3assert factorial(1000) == 402387260...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000ms
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediately
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000ms
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cached
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10) // at most 10 invocations cached
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10) // at most 10 invocations cacheddef plusAtMost = { ... }.memoizeAtMost(10)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10) // at most 10 invocations cacheddef plusAtMost = { ... }.memoizeAtMost(10)
// between 10 and 20 invocations cached
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Closure memoization
23
def plus = { a, b ‐> sleep 1000; a + b }.memoize()
assert plus(1, 2) == 3 // after 1000msassert plus(1, 2) == 3 // return immediatelyassert plus(2, 2) == 4 // after 1000msassert plus(2, 2) == 4 // return immediately // at least 10 invocations cacheddef plusAtLeast = { ... }.memoizeAtLeast(10) // at most 10 invocations cacheddef plusAtMost = { ... }.memoizeAtMost(10)
// between 10 and 20 invocations cacheddef plusAtLeast = { ... }.memoizeBetween(10, 20)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Currying improvements
24
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Currying improvements
24
// right curryingdef divide = { a, b ‐> a / b }def halver = divide.rcurry(2)assert halver(8) == 4
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Currying improvements
24
// right curryingdef divide = { a, b ‐> a / b }def halver = divide.rcurry(2)assert halver(8) == 4 // currying n‐th parameterdef joinWithSeparator = { one, sep, two ‐> one + sep + two }def joinWithComma = joinWithSeparator.ncurry(1, ', ')assert joinWithComma('a', 'b') == 'a, b'
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Builtin JSON support
• Consuming
• Producing
• Pretty-printing
25
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Builtin JSON support
26
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 }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Builtin JSON support
27
import groovy.json.* def json = new JsonBuilder() json.person { name "Guillaume" age 33 pets "Hector", "Felix"} println json.toString()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Builtin JSON support
28
import groovy.json.* println JsonOutput.prettyPrint( '''{"person":{"name":"Guillaume","age":33,''' + '''"pets":["Hector","Felix"]}}''')
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Builtin JSON support
28
import groovy.json.* println JsonOutput.prettyPrint( '''{"person":{"name":"Guillaume","age":33,''' + '''"pets":["Hector","Felix"]}}''')
{ "person": { "name": "Guillaume", "age": 33, "pets": [ "Hector", "Felix" ] }}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New AST transformations
• @Log
• @Field
• @AutoClone• @AutoExternalizable
• Controlling the execution of your code– @ThreadInterrupt, – @TimedInterrupt, – @ConditionalInterrupt
• @Canonical– @ToString, – @EqualsAndHashCode, – @TupleConstructor
• @InheritConstructor
• @WithReadLock• @WithWriteLock
• @ListenerList
29
@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
30
import groovy.util.logging.* @Logclass Car { Car() { log.info 'Car constructed' }} def c = new Car()
@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
30
import groovy.util.logging.* @Logclass Car { Car() { log.info 'Car constructed' }} def c = new Car()
Guardedw/ an if
@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
31
@Field List awe = [1, 2, 3]def awesum() { awe.sum() }assert awesum() == 6
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
• 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
Controlling code execution
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
• 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
32
Controlling code execution
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
• 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
32
Controlling code execution
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
• 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 on32
Controlling code execution
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@ThreadInterrupt
33
@ThreadInterruptimport groovy.transform.ThreadInterrupt while (true) {
// eat lots of CPU}
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@ThreadInterrupt
33
@ThreadInterruptimport groovy.transform.ThreadInterrupt while (true) {
// eat lots of CPU}
if (Thread.currentThread.isInterrupted()) throw new InterruptedException(){ }
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@ThreadInterrupt
• Two optional annotation parameters available– checkOnMethodStart (true by default)– applyToAllClasses (true by default)
33
@ThreadInterruptimport groovy.transform.ThreadInterrupt while (true) {
// eat lots of CPU}
if (Thread.currentThread.isInterrupted()) throw new InterruptedException(){ }
33
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@TimedInterrupt
• 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)
34
@TimedInterrupt(10)import groovy.transform.TimedInterrupt while (true) { // eat lots of CPU}
@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
35
@ConditionalInterrupt({ counter++ > 2 })import groovy.transform.ConditionalInterruptimport groovy.transform.Field @Field int counter = 0
100.times { println 'executing script method...'}
@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
36
import groovy.transform.ToString @ToStringclass Person { String name int age} println new Person(name: 'Pete', age: 15)// => Person(Pete, 15)
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@EqualsAndHashCode
• Provides default implementations for equals() and hashCode() methods
37
import groovy.transform.EqualsAndHashCode @EqualsAndHashCodeclass Coord { int x, y} def c1 = new Coord(x: 20, y: 5)def c2 = new Coord(x: 20, y: 5) assert c1 == c2assert c1.hashCode() == c2.hashCode()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@TupleConstructor
• Provides a «classical» constructor with all properties• Several annotation parameter options available
38
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
@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 annotations
39
@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
40
class CustomException extends Exception { CustomException() { super() } CustomException(String msg) { super(msg) } CustomException(String msg, Throwable t) { super(msg, t) } CustomException(Throwable t) { super(t) }}
@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
40
class CustomException extends Exception { CustomException() { super() } CustomException(String msg) { super(msg) } CustomException(String msg, Throwable t) { super(msg, t) } CustomException(Throwable t) { super(t) }}
import groovy.transform.*
@InheritConstructorsclass CustomException extends Exception {
}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@WithReadLock, @WithWriteLock
41
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 }}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
@WithReadLock, @WithWriteLock
41
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 }}
{
{
@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 coercion
42
@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– ASTTransformationCustomizer– SecureASTCustomizer
• But you can implement your own
43
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Imports customizer
44
def configuration = new CompilerConfiguration() def custo = new ImportCustomizer()custo.addStaticStar(Math.name)configuration.addCompilationCustomizers(custo) def result = new GroovyShell(configuration) .evaluate(" cos PI/3 ")
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Applying an AST transformation
45
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()""")
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Secure AST customizer
• Letʼs setup our environment– some imports– an import customizer to import java.lang.Math.*– prepare a secure AST customizer
46
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()
Idea: Implement an «arithmetic shell»Being able control what a user script is allowed to do: only arithmetic expressions
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Secure AST customizer
47
...secure.with {
// disallow closure creationclosuresAllowed = false // disallow method definitionsmethodDefinitionAllowed = false
// empty white list => forbid importsimportsWhitelist = [] staticImportsWhitelist = []// only allow the java.lang.Math.* static importstaticStarImportsWhitelist = ['java.lang.Math'
...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Secure AST customizer
48
...// language tokens allowedtokensWhitelist = [
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 callsreceiversClassesWhiteList = [
Math, Integer, Float, Double, Long, BigDecimal ]}...
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Secure AST customizer
• Ready to evaluate our arithmetic expressions!
• But the following would have failed:
49
shell.evaluate 'System.exit(0)'
...def config = new CompilerConfiguration()config.addCompilationCustomizers(imports, secure)
def shell = new GroovyShell(config) shell.evaluate 'cos PI/3'
@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– a multiline GString with different escaping rules
50
def (name, date) = ["Guillaume", "Oct, 26th"]def dollarSlashy = $/ Hello $name, today we're ${date} $ dollar‐sign $$ dollar‐sign \ backslash / slash $/ slash/$
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// count
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count by
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }assert [(true):2, (false):4] == 'Groovy'.toList().countBy{ it == 'o' }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 }assert [(true):2, (false):4] == 'Groovy'.toList().countBy{ it == 'o' }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef map = [a: 1, bbb: 4, cc: 5, dddd: 2]
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef map = [a: 1, bbb: 4, cc: 5, dddd: 2] assert map.max { it.key.size() }.key == 'dddd'
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef map = [a: 1, bbb: 4, cc: 5, dddd: 2] assert map.max { it.key.size() }.key == 'dddd'assert map.min { it.value }.value == 1
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef map = [a: 1, bbb: 4, cc: 5, dddd: 2] assert map.max { it.key.size() }.key == 'dddd'assert map.min { it.value }.value == 1
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef 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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef 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()
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef 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 }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
New GDK methods
51
// countassert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 // count byassert [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 closuresdef 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 }
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color {
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with as
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color // implicit coercion
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color // implicit coercionColor b = "blue"
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color // implicit coercionColor b = "blue"
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color // implicit coercionColor b = "blue" // with GStrings too
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
(G)String to Enum coercion
52
enum Color { red, green, blue} // coercion with asdef r = "red" as Color // implicit coercionColor b = "blue" // with GStrings toodef g = "${'green'}" as Color
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Customizing the Groovysh prompt
53
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Launching remote scripts
• With the Groovy command, you can launch remote scripts
• Be careful to what youʼre executing :-)
54
> groovy http://groovyconsole.appspot.com/raw/110001
What’s cookingfor 1.9?
@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
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 InvokeDynamic
57
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Binary literals
• We had decimal, octal and hexadecimal notations for number literals
• We can now use binary representations too
58
int x = 0b10101111assert x == 175 byte aByte = 0b00100001assert aByte == 33 int anInt = 0b1010000101000101assert anInt == 41285
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Underscore in literals
• Now we can also add underscores in number literals for more readability
59
long creditCardNumber = 1234_5678_9012_3456Llong socialSecurityNumbers = 999_99_9999Lfloat monetaryAmount = 12_345_132.12long hexBytes = 0xFF_EC_DE_5Elong hexWords = 0xFFEC_DE5Elong maxLong = 0x7fff_ffff_ffff_ffffLlong alsoMaxLong = 9_223_372_036_854_775_807Llong bytes = 0b11010010_01101001_10010100_10010010
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Multicatch
• One block for multiple exception caught– rather than duplicating the block
60
try { /* ... */} catch(IOException | NullPointerException e) { /* one block to treat 2 exceptions */}
@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 easily
61
@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
• Provide hooks for setting up EMCs / DGM methods, etc.
62
@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 methods– etc...
63
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
A typo in your variable or method names
64
import groovy.transform.StaticTypes void method() {} @TypeChecked test() { // Cannot find matching method metthhoood() metthhoood() def name = "Guillaume" // variable naamme is undeclared println naamme}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
A typo in your variable or method names
64
import groovy.transform.StaticTypes void method() {} @TypeChecked test() { // Cannot find matching method metthhoood() metthhoood() def name = "Guillaume" // variable naamme is undeclared println naamme}
Compilationerrors!
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Complain on wrong assignments
65
// cannot assign value of type... to variable...int x = new Object()Set set = new Object() def o = new Object()int x = o String[] strings = ['a','b','c']int str = strings[0] // cannot find matching method plus()int i = 0i += '1'
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Complain on wrong assignments
65
// cannot assign value of type... to variable...int x = new Object()Set set = new Object() def o = new Object()int x = o String[] strings = ['a','b','c']int str = strings[0] // cannot find matching method plus()int i = 0i += '1'
Compilationerrors!
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Complain on wrong return types
66
String method() { 'String' }// cannot assign value of type String...int x = method()
// checks if/else branch return valuesint method() { if (true) { 'String' } else { 42 }}// works for switch/case & try/catch/finally // transparent toString() impliedString greeting(String name) { def sb = new StringBuilder() sb << "Hi" << name}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Complain on wrong return types
66
String method() { 'String' }// cannot assign value of type String...int x = method()
// checks if/else branch return valuesint method() { if (true) { 'String' } else { 42 }}// works for switch/case & try/catch/finally // transparent toString() impliedString greeting(String name) { def sb = new StringBuilder() sb << "Hi" << name}
Compilationerrors!
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Type inference
67
@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 }}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Staticly checked method & dynamic method
68
@TypeCheckedString greeting(String name) { // call method with dynamic behavior // but with proper signature generateMarkup(name.toUpperCase())} // usual dynamic behaviorString generateMarkup(String name) { def sw = new StringWriter() new MarkupBuilder(sw).html { body { div name } } sw.toString()}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Bytecode viewer
• Groovy Consoleʼs bytecode viewerfrom the AST browser window– select class
generation phase– select a class node
69
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Disable Global AST transformations
70
// witout a specific configuration, the AST builder worksdef 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 appliedshell = new GroovyShell(config) // <‐‐ with the configurationshouldFail { shell.evaluate(script) // fails}
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Summary
71
ROCKS!
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
Thank you!
Guillaume Laforge
Head of Groovy Development
Email: [email protected]
Twitter: @glaforge
Google+: http://gplus.to/glaforge
72
Q&A — Got questions, Really?
@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge
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