groovy to infinity and beyond - gr8conf europe 2010 - guillaume laforge
TRANSCRIPT
to Infinity and Beyond
mercredi 19 mai 2010
Guillaume LaforgeSpringSource, a division of VMWare
to infinity and beyond!
mercredi 19 mai 2010
Guillaume LaforgeGroovy Project Manager
on Groovy since 2003!
JSR-241 Spec Lead
Head of Groovy Developmentat SpringSource (division of VMWare)
Initiator of the Grails framework
Creator of the Gaelyk toolkit
Co-author of Groovy in Action
International speaker
mercredi 19 mai 2010
AgendaPast
Groovy 1.6 flashback
PresentGroovy 1.7 novelties
A few Groovy 1.7.x refinements
FutureWhat’s cooking for 1.8 and beyond
mercredi 19 mai 2010
looking into the Pastmercredi 19 mai 2010
Big highlights of Groovy 1.6Greater compile-time and runtime performanceMultiple assignmentsOptional return for if/else and try/catch/finallyJava 5 annotation definitionAST TransformationsThe Grape module and dependency systemVarious Swing related improvementsJMX BuilderMetaprogramming additionsJSR-223 scripting engine built-inOut-of-the-box OSGi support
mercredi 19 mai 2010
Multiple assignement// multiple assignmentdef (a, b) = [1, 2]assert a == 1 && b == 2 // with typed variablesdef (int c, String d) = [3, "Hi"]assert c == 3 && d == "Hi" def geocode(String place) { [48.8, 2.3] }def lat, lng// assignment to existing variables(lat, lng) = geocode('Paris') // classical variable swaping example(a, b) = [b, a]
mercredi 19 mai 2010
More optional return// optional return for if statements
def m1() { if (true) 1 else 0}assert m1() == 1 // optional return for try/catch/finally
def m2(bool) { try { if (b) throw new Exception()
1 } catch (any) { 2 } finally { 3 }}assert m2(true) == 2 && m2(false) == 1
mercredi 19 mai 2010
AST Transformation (1/2)Groovy 1.6 introduced AST Transformations
AST: Abstract Syntax Tree
Ability to change what’s being compiled by the Groovy compiler... at compile time
No runtime impact!
Change the semantics of your programs! Even hijack the Groovy syntax!
Implementing recurring patterns in your code base
Remove boiler-plate code
Two kinds: global and local (triggered by anno)
mercredi 19 mai 2010
AST Transformations (2/2)Transformations introduced in 1.6
@Singleton
@Immutable, @Lazy, @Delegate
@Newify
@Category, @Mixin
@PackageScope
Swing’s @Bindable and @Vetoable
Grape’s own @Grab
mercredi 19 mai 2010
@ImmutableTo properly implement immutable classes
No mutations — state musn’t change
Private final fields
Defensive copying of mutable components
Proper equals() / hashCode() / toString() for comparisons or fas keys in maps
@Immutable class Coordinates { Double lat, lng}def c1 = new Coordinates(lat: 48.8, lng: 2.5)
def c2 = new Coordinates(48.8, 2.5)assert c1 == c2
mercredi 19 mai 2010
Grab a grape!Simple distribution and sharing of Groovy scripts
Dependencies stored locallyCan even use your own local repositories
@Grab(group = 'org.mortbay.jetty',
module = 'jetty‐embedded',
version = '6.1.0')
def startServer() { def srv = new Server(8080)
def ctx = new Context(srv , "/", SESSIONS)
ctx.resourceBase = "."
ctx.addServlet(GroovyServlet, "*.groovy")
srv.start()}
mercredi 19 mai 2010
Metaprogramming additions (1/2)ExpandoMetaClass DSL
factoring EMC changes
Number.metaClass { multiply { Amount amount ‐> amount.times(delegate) } div { Amount amount ‐> amount.inverse().times(delegate)
}}
mercredi 19 mai 2010
Metaprogramming additions (2/2)Runtime mixins
class FlyingAbility { def fly() { "I'm ${name} and I fly!" }
} class JamesBondVehicle { String getName() { "James Bond's vehicle" }
} JamesBondVehicle.mixin FlyingAbility
assert new JamesBondVehicle().fly() ==
"I'm James Bond's vehicle and I fly!"
mercredi 19 mai 2010
JMX BuilderA DSL for handling JMX
in addition of Groovy MBean// Create a connector serverdef jmx = new JmxBuilder()jmx.connectorServer(port:9000).start()
// Create a connector clientjmx.connectorClient(port:9000).connect()
//Export a beanjmx.export { bean new MyService() } // Defining a timerjmx.timer(name: "jmx.builder:type=Timer",
event: "heartbeat", period: "1s").start()
// JMX listenerjmx.listener(event: "someEvent", from: "bean",
call: { evt ‐> /* do something */ })
mercredi 19 mai 2010
into the Present...mercredi 19 mai 2010
Big highlights of Groovy 1.7Anonymous Inner Classes and Nested ClassesAnnotations anywhereGrape improvementsPower AssertsAST ViewerAST BuilderCustomize the Groovy Truth!Rewrite of the GroovyScriptEngineGroovy Console improvementsSQL support refinements
mercredi 19 mai 2010
AIC and NCAnonymous Inner Classe and Nested Classes
mercredi 19 mai 2010
AIC and NCAnonymous Inner Classe and Nested Classes
For Java
copy’n paste
compatibility
sake :-)
mercredi 19 mai 2010
Annonymous Inner Classes
boolean called = false
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called = true
}}, 0)
sleep 100assert called
mercredi 19 mai 2010
Annonymous Inner Classes
boolean called = false
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called = true
}}, 0)
sleep 100assert called
{ called = true } as TimerTask
mercredi 19 mai 2010
Nested Classes
class Environment { static class Production extends Environment {}
static class Development extends Environment {}
} new Environment.Production()
mercredi 19 mai 2010
Anotations anywhere
You can now put annotationson imports
on packages
on variable declarations
Examples with @Grab following...
mercredi 19 mai 2010
Grape improvements (1/3)@Grab on import
@Grab(group = 'net.sf.json‐lib',
module = 'json‐lib',
version = '2.3', classifier = 'jdk15')import net.sf.json.groovy.*
assert new JsonSlurper().parseText(
new JsonGroovyBuilder().json {
book(title: "Groovy in Action",
author:"Dierk König et al")
}.toString()).book.title == "Groovy in Action"
mercredi 19 mai 2010
Grape improvements (2/3)Shorter module / artifact / version parameter
Example of an annotation on a variable declaration
@Grab('net.sf.json‐lib:json‐lib:2.3:jdk15')
def builder = new net.sf.json.groovy.JsonGroovyBuilder()
def books = builder.books { book(title: "Groovy in Action", author: "Dierk Koenig")
}assert books.toString() == '{"books":{"book":{"title":"Groovy in Action",' +
'"author":"Dierk Koenig"}}}'''
mercredi 19 mai 2010
Grape improvements (3/3)Groovy 1.7 introduced Grab resolver
For when you need to specify a specific repositoryfor a given dependency
@GrabResolver( name = 'restlet.org', root = 'http://maven.restlet.org')
@Grab('org.restlet:org.restlet:1.1.6')
import org.restlet.Restlet
mercredi 19 mai 2010
Power Asserts (1/2)Much better assert statement!
Invented and developed in the Spock framework
Given this script...
def energy = 7200 * 10**15 + 1def mass = 80def celerity = 300000000 assert energy == mass * celerity ** 2
mercredi 19 mai 2010
Power Asserts (2/2)You’ll get a more comprehensible output
mercredi 19 mai 2010
Spock testing framework
mercredi 19 mai 2010
Easier AST TransformationsAST Transformations are a very powerful feature
But are still rather hard to developNeed to know the AST API closely
To help with authoring your own transformations, we’ve introduced
the AST Viewer in the Groovy Console
the AST Builder
mercredi 19 mai 2010
AST Viewer
mercredi 19 mai 2010
AST Builder
// Ability to build AST parts
// ‐‐> from a Stringnew AstBuilder().buildFromString(''' "Hello" '''
)
// ‐‐> from codenew AstBuilder().buildFromCode { "Hello" }
// ‐‐> from a specification
List<ASTNode> nodes = new AstBuilder().buildFromSpec {
block { returnStatement {
constant "Hello"
} }}
mercredi 19 mai 2010
Customize the Groovy Truth!Ability to customize the truth by implementing a boolean asBoolean() method
class Predicate { boolean value boolean asBoolean() { value }
} def truePred = new Predicate(value: true)
def falsePred = new Predicate(value: false)
assert truePred && !falsePred
mercredi 19 mai 2010
SQL support refinements
// batch statementssql.withBatch { stmt ‐>
["Paul", "Jochen", "Guillaume"].each { name ‐>
stmt.addBatch "insert into PERSON (name) values ($name)"
}} // transaction supportdef persons = sql.dataSet("person")
sql.withTransaction { persons.add name: "Paul" persons.add name: "Jochen"
persons.add name: "Guillaume"
persons.add name: "Roshan"
}
mercredi 19 mai 2010
Groovy 1.7.x changes
Groovy 1.7.1 and 1.7.2 have been released
Groovy 1.7.3 is coming soon
Here’s what’s new!
mercredi 19 mai 2010
Map improvements
// map auto‐vificationdef m = [:].withDefault { key ‐> "Default" }
assert m['z'] == "Default"
assert m['a'] == "Default"
// default sortm.sort()
// sort with a comparatorm.sort({ a, b ‐> a <=> b } as Comparator)
mercredi 19 mai 2010
XML back to StringAbility to retrieve the XML string from a node from an XmlSlurper GPathResult
def xml = """<books> <book isbn="12345">Groovy in Action</book>
</books>"""def root = new XmlSlurper().parseText(xml)
def someNode = root.bookdef builder = new StreamingMarkupBuilder()
assert builder.bindNode(someNode).toString() ==
"<book isbn='12345'>Groovy in Action</book>"
mercredi 19 mai 2010
Currying improvements
// 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'
mercredi 19 mai 2010
New icon for the Swing console
mercredi 19 mai 2010
New icon for the Swing console
mercredi 19 mai 2010
New String methodsprintln """ def method() { return 'bar' }""".stripIndent()
println """ |def method() { | return 'bar' |}""".stripMargin('|')
// string "translation" (UNIX tr)
assert 'hello'.tr('z‐a', 'Z‐A') == 'HELLO'
assert 'Hello World!'.tr('a‐z', 'A') == 'HAAAA WAAAA!'
assert 'Hello World!'.tr('lloo', '1234') == 'He224 W4r2d!'
// capitalize the first letter
assert 'h'.capitalize() == 'H'
assert 'hello'.capitalize() == 'Hello'
assert 'hello world'.capitalize() == 'Hello world'
// tab/space (un)expansion (UNIX expand command)
assert '1234567\t8\t '.expand() == '1234567 8 '
assert ' x '.unexpand() == ' x\t '
mercredi 19 mai 2010
...and beyond!mercredi 19 mai 2010
Groovy 1.8 & beyondStill subject to discussion
Always evolving roadmap
Things may change!
mercredi 19 mai 2010
What’s cooking?mercredi 19 mai 2010
What we’re working onMore runtime performance improvements
Closure annotations
Gradle build
Modularizing Groovy
Align with JDK 7 / Java 7 / Project Coin
Enhanced DSL support
AST Templates
Towards MOP 2
mercredi 19 mai 2010
«Blackdrag» revealedthe black magic!
mercredi 19 mai 2010
Closure annotationsGroovy 1.5 brought Java 5 annotations
What if... we could go beyond what Java offered?In 1.7, we can put annotations on packages, imports and variable declarations
But annotations are still limited in terms of parameters they allow
Here comes closure annotations!Groovy 1.8 will give us the ability to access annotation with closure parameters at runtime
mercredi 19 mai 2010
GContractsClosures are already allowed in the Groovy 1.7 Antlr grammar
Andre Steingreß created GContracts, a «design by contract» module
// a class invariant@Invariant({ name.size() > 0 && age > ageLimit() })
// a method pre‐condition@Requires({ message != null }) // a method post‐condition@Ensures({ returnResult % 2 == 0 })
mercredi 19 mai 2010
mercredi 19 mai 2010
mercredi 19 mai 2010
More adhoc build
More modular Groovy
More from Hans!
mercredi 19 mai 2010
More modular build«Not everybody needs everything!» ™
A lighter Groovy-corewhat’s in groovy-all?
Modulestest, jmx, swing, xml, sql, web, template
integration (bsf, jsr-223)
tools (groovydoc, groovyc, shell, console, java2groovy)
mercredi 19 mai 2010
Java 7 / JDK 7 / Project CoinJSR-292 InvokeDynamic
Simple Closures?
Proposals from Project CoinStrings in switch
Automatic Resource Management
Improved generics type inference (diamond <>)
Simplified varargs method invocation
Better integral literals
Language support for collections
mercredi 19 mai 2010
Improved DSL support
GEP-3: an extended command expression DSLGroovy Extension Proposal #3
A Google Summer of Code student will work on that
Command expressionsbasically top-level statements without parens
combine named and non-named arguments in the mixfor nicer Domain-Specific Languages
mercredi 19 mai 2010
Before GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls
Before
send("Hello").to("Jochen")send("Hello", from: "Guillaume").to("Jochen")
sell(100.shares).of(MSFT)
take(2.pills).of(chloroquinine).in(6.hours)
every(10.minutes).execute { }
given { }.when { }.then { }
blend(red, green).of(acrylic)
mercredi 19 mai 2010
With GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls
After
send "Hello" to "Jochen"send "Hello", from: "Guillaume" to "Jochen"
sell 100.shares of MSFT
take 2.pills of chloroquinine in 6.hours
every 10.minutes execute { }
given { } when { } then { }
blend red, green of acrylic
mercredi 19 mai 2010
With GEP-3The idea: extend command-expressions, beyond top-level statements, for chained method calls
After
send "Hello" to "Jochen"send "Hello", from: "Guillaume" to "Jochen"
sell 100.shares of MSFT
take 2.pills of chloroquinine in 6.hours
every 10.minutes execute { }
given { } when { } then { }
blend red, green of acrylic
Less parens& commas
mercredi 19 mai 2010
AST TemplatesSince AST, it’s easier to write AST Transformations
But we can even do better!
Hamlet D’Arcy is working on a new proposalGEP-4 — AST Templates
mercredi 19 mai 2010
a new
MOP
mercredi 19 mai 2010
Towards a new MOP?The Meta-Object Protocol show its age
different stratification layersDGM, categories, custom MetaClasses, ExpandoMetaClass...
different characteristicsscope: global, local, thread-bound
works across the hierarchy or not
A better MOP could...help for performance
offer more granularity
let the developer choose the characteristics he needs
provide a layered approach of changes
mercredi 19 mai 2010
Some potential modulesGPars was considered a potential module for addition into core
but got a life of its own!
Parser combinatorsfor when you hit the walls of the Groovy syntax
and AST transformations won’t cut it
Pattern matching
mercredi 19 mai 2010
Summary (1/2)No need to wait for Java 7, 8, 9...
closures, properties, interpolated strings, extended annotations, metaprogramming, [YOU NAME IT]...
mercredi 19 mai 2010
Summary (1/2)No need to wait for Java 7, 8, 9...
closures, properties, interpolated strings, extended annotations, metaprogramming, [YOU NAME IT]...
Groovy’s
still innovative
since 2003!
mercredi 19 mai 2010
Summary (2/2)But it’s more than just a language, it’s a very rich and active ecosystem!
Grails, Griffon, Gradle, GPars, Spock, Gaelyk...
mercredi 19 mai 2010
Thanks for your attention!
Guillaume Laforge
Head of Groovy Development
Email: [email protected]
Twitter: @glaforge
mercredi 19 mai 2010
Questions & Answers
mercredi 19 mai 2010
Images used in this presentationHouse / past: http://www.flickr.com/photos/jasonepowell/3680030831/sizes/o/
Present clock: http://www.flickr.com/photos/38629278@N04/3784344944/sizes/o/
Future: http://www.flickr.com/photos/befuddledsenses/2904000882/sizes/l/
Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/
Black dragon: http://www.free-computer-wallpapers.com/pictures/Fantasy-wallpaper/Black_Dragon
Puzzle: http://www.everystockphoto.com/photo.php?imageId=263521
Light bulb: https://newsline.llnl.gov/retooling/mar/03.28.08_images/lightBulb.png
Spock: http://altoladeira.files.wordpress.com/2009/07/spock2.jpg
mercredi 19 mai 2010