SlideShare a Scribd company logo
Dr Paul King
Groovy Lead for Object Computing Inc.
@paulk_asert
http:/slideshare.net/paulk_asert/awesome-groovy
https://github.com/paulk-asert/awesome-groovy
Apache Groovy:
The Awesome Parts
FRIEND OF GROOVY
Part 1: Introducing Groovy?
What is Groovy?
4
Groovy = Java – boiler plate code
+ closures (1st class FP)
+ extensible type system
+ runtime & compile-time metaprogramming
+ flexible language grammar (DSLs)
+ scripting
+ GDK library
“Groovy is like a super version of Java.
It leverages Java features but adds productivity features
and provides great flexibility and extensibility.”
Why Groovy?
Java
Why Groovy?
Too verbose
Support
functional
programming
Better
concurrency
Evolves
too slowly
I need
feature
XXX
Too complex
for some
situations
More
flexibility
Java
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Good IDE
support
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Good IDE
support
Custom
features
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Support
concurrency
Good IDE
support
Custom
features
Java
integration
Why Groovy?
Groovy
Make it
simplerMake it
dynamic
Support
simple
scripting
Support
functional
style
Support
concurrency
Good IDE
support
Custom
features
Java
integration
Java code for list manipulation
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Groovy code for list manipulation
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Rename
Main.java
to
Main.groovy
Some Java Boilerplate identified
import java.util.List;
import java.util.ArrayList;
class Main {
private List keepShorterThan(List strings, int length) {
List result = new ArrayList();
for (int i = 0; i < strings.size(); i++) {
String s = (String) strings.get(i);
if (s.length() < length) {
result.add(s);
}
}
return result;
}
public static void main(String[] args) {
List names = new ArrayList();
names.add("Ted"); names.add("Fred");
names.add("Jed"); names.add("Ned");
System.out.println(names);
Main m = new Main();
List shortNames = m.keepShorterThan(names, 4);
System.out.println(shortNames.size());
for (int i = 0; i < shortNames.size(); i++) {
String s = (String) shortNames.get(i);
System.out.println(s);
}
}
}
Are the semicolons
needed?
And shouldn’t
we us more
modern list
notation?
Why not
import common
libraries?
Do we need
the static types?
Must we always
have a main
method and
class definition?
How about
improved
consistency?
Java Boilerplate removed
def keepShorterThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() < length) {
result.add(s)
}
}
return result
}
names = new ArrayList()
names.add("Ted"); names.add("Fred")
names.add("Jed"); names.add("Ned")
System.out.println(names)
shortNames = keepShorterThan(names, 4)
System.out.println(shortNames.size())
for (s in shortNames) {
System.out.println(s)
}
More Java Boilerplate identified
def keepShorterThan(strings, length) {
def result = new ArrayList()
for (s in strings) {
if (s.size() < length) {
result.add(s)
}
}
return result
}
names = new ArrayList()
names.add("Ted"); names.add("Fred")
names.add("Jed"); names.add("Ned")
System.out.println(names)
shortNames = keepShorterThan(names, 4)
System.out.println(shortNames.size())
for (s in shortNames) {
System.out.println(s)
}
Shouldn’t we
have special
notation for lists?
And special
facilities for
list processing?
Is ‘return’
needed at end?
Is the method
now needed?
Simplify common
methods?
Remove unambiguous
brackets?
Boilerplate removed = nicer Groovy version
names = ["Ted", "Fred", "Jed", "Ned"]
println names
shortNames = names.findAll{ it.size() < 4 }
println shortNames.size()
shortNames.each{ println it }
["Ted", "Fred", "Jed", "Ned"]
3
Ted
Jed
Ned
Output:
Or Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
// plus a DSL implementation
Or Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
names = []
def of, having, less
def given(_the) { [names:{ Object[] ns -> names.addAll(ns)
[and: { n -> names += n }] }] }
def the = [
number: { _of -> [names: { _having -> [size: { _less -> [than: { size ->
println names.findAll{ it.size() < size }.size() }]}] }] },
names: { _having -> [size: { _less -> [than: { size ->
names.findAll{ it.size() < size }.each{ println it } }]}] }
]
def all = [the: { println it }]
def display(arg) { arg }
Or Groovy DSL version if required
• Or use GDSL (IntelliJ IDEA) or DSLD (Eclipse)
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
Or typed Groovy DSL version if required
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
…
enum The { the }
enum Having { having }
enum Of { of }
…
class DisplayThe {
DisplayTheNamesHaving names(Having having) {
new DisplayTheNamesHaving()
}
DisplayTheNumberOf number(Of of) {
new DisplayTheNumberOf()
}
}
…
// plus 50 lines
Or typed Groovy DSL version if required
Groovy DSL being debugged
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}

@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", "Fred", "Jed" and "Ned"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
Or typed Groovy DSL version if required
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", “Mary", "Jed" and “Pete"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
Or typed Groovy DSL version if required
@TypeChecked(extensions='EdChecker.groovy')
def method() {
given the names "Ted", “Mary", "Jed" and “Pete"
display all the names
display the number of names having size less than 4
display the names having size less than 4
}
afterMethodCall { mc ->
mc.arguments.each {
if (isConstantExpression(it)) {
if (it.value instanceof String && !it.value.endsWith('ed')) {
addStaticTypeError("I don't like the name '${it.value}'", mc)
}
}
}
}
Or typed Groovy DSL version if required

What style of language is Groovy?
Groovy Style
• Imperative/OO but somewhat
paradigm agnostic
•Dynamic, optionally static (gradual
extensible typing)
• Extensible language features
through metaprogramming
Part 2: What makes Groovy Awesome?
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain specific
language (DSL) support
• Ecosystem
• Community/Team
Awesome
What makes Groovy Awesome?
• Java integration
• Builds up on Java
• Tight integration
• Polyglot friendly
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Java Integration
• Groovy is Java’s friend
Java
Groovy
Java Integration
• Standing on the shoulders of Giants
• Some limitations inherited but much
gained through new releases of Java
• Rock solid foundation
• Can ease migration to new versions
of Java
Java
Groovy
Java Integration
• Seamless integration
• IDEs provide cross-language compile,
navigation, and refactoring
• Arbitrarily mix source language
• Drop-in replace
any class
• Overloaded methods
• Syntax alignment
• Shared data types
Java
Groovy
Java Integration
• Seamless integration
• IDEs provide cross-language compile,
navigation, and refactoring
• Arbitrarily mix source language
• Drop-in replace
any class
• Overloaded methods
• Syntax alignment
• Shared data types
Java
Groovy
Java Integration
• Polyglot friendly
• Typically integrates well with other
languages which integrate with Java
• JRuby
• Jython
• Scala
• Frege
• Clojure
• R through Renjin
• JavaScript
(Rhino/Nashorn)
Java Integration
• Polyglot friendly
• JSR-223 scripting
to talk to JavaScript
import javax.script.ScriptEngineManager
def mgr = new ScriptEngineManager()
def engine = mgr.getEngineByName('nashorn')
assert engine.eval('''
function factorial(n) {
if (n == 0) { return 1; }
return n * factorial(n - 1);
}
factorial(4)
''') == 24.0
Java
GroovyJavaScript
Java Integration
• Polyglot friendly: R integration
@GrabResolver('https://nexus.bedatadriven.com/content/groups/public')
@Grab('org.renjin:renjin-script-engine:0.7.0-RC7')
import javax.script.ScriptEngineManager
def mgr = new ScriptEngineManager()
def engine = mgr.getEngineByName('Renjin')
engine.with {
eval '''
factorial <- function(x) {
y <- 1
for (i in 1:x) { y <- y * i }
return(y)
}
'''
assert eval('factorial(4)')[0] == 24
}
Java
GroovyR
Grooscript
@Grab('org.grooscript:grooscript:1.2.0')
import org.grooscript.GrooScript
import javax.script.ScriptEngineManager
def groojs = GrooScript.convert '''
def sayHello = { println "Hello ${it}!" }
['Groovy','JavaScript','GrooScript'].each sayHello''',
[initialText: 'var console = { log: print }',
addGsLib: 'grooscript.min']
new ScriptEngineManager().getEngineByName("nashorn").eval(groojs)
Hello Groovy!
Hello JavaScript!
Hello GrooScript!
Jorge Franco, grooscript.org
Convert Groovy subset to JavaScript
Support: Gradle, Grails, NPM
Demos: react.js, node.js, Pollock
Converts: Classes, closures, Date
primitives, ranges, String/GString
Special: builder, templates, gQuery
What makes Groovy Awesome?
• Java integration
• Builds up on Java
• Tight integration
• Polyglot friendly
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
• Friend of Java
• Integration
• Good JVM Citizen
What makes Groovy Awesome?
• Java integration
• Scripting support
• Simplified scripting
• Separation of concerns
• Security sandbox
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
Scripting
• Terse format
• Isolation
• Domain-Specific
Languages (DSLs)
• Security
• Flexibility
Scripting
• Leave out surrounding class
• Entire source file:
public class Script {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
println "Hello world"
Scripting
• Various approaches supported
• GroovyShell
• GroovyScriptEngine
• GroovyClassLoader
• Spring
• JSR-223
• Base scripts
• allows predefined methods
• Binding
• allows predefined variables
• Customizers
• add imports, static imports
• lock down AST to a subset
• apply any AST transform transparently
Scripting
Scripting
Scripting
Scripting
class Robot {
void move(dir) {
println "robot moved $dir"
}
}
def robot = new Robot()
Scripting
import static Direction.*
enum Direction {
left, right, forward, backward
}
class Robot {
void move(Direction dir) {
println "robot moved $dir"
}
}
def robot = new Robot()
robot.move left
Scripting
move left
def robot = new Robot()
def binding = new Binding(
robot: robot,
move: robot.&move,
*: Direction.values().collectEntries {
[(it.name()): it]
}
)
def shell = new GroovyShell(binding)
shell.evaluate new File(args[0]).text
Scripting
move left
def robot = new Robot()
def binding = new Binding(/* ... */)
def imports = new ImportCustomizer().addStaticStars('java.lang.Math')
def timeout = new ASTTransformationCustomizer(value: 2, TimedInterrupt)
def secure = new SecureASTCustomizer().with {
closuresAllowed = false
importsWhitelist = []
tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, /*...*/ ]
//...
}
def sysExit = new CompilationCustomizer(CANONICALIZATION) {
void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) {
new ClassCodeVisitorSupport() {
void visitMethodCallExpression(MethodCallExpression call) {
// check for System.exit()
}
// ...
}.visitClass(cn)
}
}
def config = new CompilerConfiguration()
config.addCompilationCustomizers(imports, timeout, secure, sysExit)
def shell = new GroovyShell(binding, config)
Scripting
move left
move forward at 3.km/h
More
examples
later
What makes Groovy Awesome?
• Java integration
• Scripting support
• Simplified scripting
• Separation of concerns
• Security sandbox
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Awesome
• Simpler scripting
• Separation of concerns
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Object-oriented
• Functional, Closures
• Logic/Dataflow programming
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Multiparadigm
• Imperative roots from Java
• OO abstractions: classes,
interfaces, inheritance
• Properties
• Traits
• First class functional support via closures
• External libraries for advanced features
• Other paradigms via libraries
• Logic, dataflow, reactive
Awesome
Multiparadigm
Imperative/OO
Logic programming
Functional
Rich OO features
• Classes (and scripts, GroovyBeans)
• Fields (and properties)
• Methods, constructors, multi-methods, named and default parameters
• Inheritance (behavior and implementation), interfaces, traits
• Type aliases
• Packages
• Special accessor notation, spread operators, GPath, safe navigation
Traits
/**
* Things that hop
* @author Grace
*/
trait Hopper {
String jump() { "I'm jumping!" }
}
class Kangaroo implements Hopper {}
def skip = new Kangaroo()
assert skip.jump() == "I'm jumping!"
Rich functional features
• Closures
• First-class functions
• Higher-order functions
• Map, reduce, filter
• Mutable & immutable data
• Recursion
• Lazy & eager evaluation
• Advanced FP techniques
• Memoization, Trampolines, Composition, Curry
• Concurrency
map/filter/reduce
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
map/filter/reduce (+ functional style)
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
def young = { person, threshold ->
person.age < threshold
}.rcurry(40).memoize()
assert people
.findAll(young)
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
map/filter/reduce (+ with streams)
@Canonical
class Person {
String name
int age
}
def people = [
new Person('Peter', 45),
new Person('Paul', 35),
new Person('Mary', 25)
]
assert people
.findAll{ it.age < 40 }
.collect{ it.name.toUpperCase() }
.sort()
.join(', ') == 'MARY, PAUL'
// requires JRE 8
def commaSep = Collectors.joining(", ")
assert people.stream()
.filter{ it.age < 40 }
.map{ it.name.toUpperCase() }
.sorted()
.collect(commaSep) == 'MARY, PAUL'
Logic/Constraint programming
• Logic programming
• Declarative style
• Logic clauses for example Prolog
• Constraint programming
• Declarative style similar to logic programming but contain constraints which
must be satisfied
• Relations between variables are stated as constraints
• Not a step or sequence of steps to execute, but rather the properties of a
solution to be found
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
How many of each animal?
Constraint programming example
@Grab('org.choco-solver:choco-solver:4.0.4')
import org.chocosolver.solver.Model
def m = new Model()
def totalAnimals = 7
def totalLegs = 20
def numCranes = m.intVar('Cranes', 0, totalAnimals, true)
def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true)
def numCraneLegs = m.intScaleView(numCranes, 2)
def numTortoiseLegs = m.intScaleView(numTortoises, 4)
m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post()
m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post()
if (m.solver.solve())
println "$numCranesn$numTortoises"
else
println "No Solutions" Cranes = 4
Tortoises = 3
ChocoCraneTortoise.groovy
See also: JSR-331 Constraint Programming API
Dataflow programming
• Declarative style
• Emphasizes the movement of data
• models programs as a series of connected tasks
• A task has explicitly defined inputs and outputs
• runs as soon as all of its inputs become available
• Inherently parallel
GPars
• Library classes and DSL allowing
you to handle tasks concurrently:
• Data Parallelism map, filter, reduce functionality
in parallel with parallel array support
• Asynchronous functions extend the Java executor
services to enable multi-threaded closure processing
• Dataflow Concurrency supports natural
shared-memory concurrency model, using
single-assignment variables
• Actors provide Erlang/Scala-like actors
including "remote" actors on other machines
• Safe Agents provide a non-blocking mt-safe
reference to mutable state; like "agents" in Clojure
72
Awesome
Concurrency challenge
• We can analyse the example’s task graph:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
def a = 5
def b = f1(a)
def c = f2(a)
def d = f3(c)
def f = f4(b, d)
assert f == 10
Concurrency challenge
• We can analyse the example’s task graph:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
def a = 5
def b = f1(a)
def c = f2(a)
def d = f3(c)
def f = f4(b, d)
assert f == 10
f2
f3
f1
f4
aa
b
c
d
f
Concurrency challenge
• Manually using asynchronous functions:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import static groovyx.gpars.GParsPool.withPool
withPool(2) {
def a = 5
def futureB = f1.callAsync(a)
def c = f2(a)
def d = f3(c)
def f = f4(futureB.get(), d)
assert f == 10
}
f2
f3
f1
f4
aa
futureB
c
d
f
Concurrency challenge
• And with GPars Dataflows:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import groovyx.gpars.dataflow.Dataflows
import static groovyx.gpars.dataflow.Dataflow.task
new Dataflows().with {
task { a = 5 }
task { b = f1(a) }
task { c = f2(a) }
task { d = f3(c) }
task { f = f4(b, d) }
assert f == 10
}
f2
f3
f1
f4
aa
b
c
d
f
Concurrency challenge
• And with GPars Dataflows:
def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 +
[{ x, y -> x + y }]
import groovyx.gpars.dataflow.Dataflows
import static groovyx.gpars.dataflow.Dataflow.task
new Dataflows().with {
task { f = f4(b, d) }
task { d = f3(c) }
task { c = f2(a) }
task { b = f1(a) }
task { a = 5 }
assert f == 10
}
f2
f3
f1
f4
aa
b
c
d
f
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Object-oriented
• Functional, Closures
• Logic/dataflow programming
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
• Ability to use imperative
when needed for speed
• Numerous declarative
approaches available
when it makes sense
Awesome
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Dynamic strong typing
• Static type checking
• Extensible
• Type inference
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
Gradual typing
• Dynamic by default
• Gradual typing
• Static type checking
• Extensible type system
Awesome
Dynamic vs static
82
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Dynamic vs static
83
Gradual
Type-time?
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Dynamic vs static
84
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
Dynamic vs static
85
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
Duck-typing
Dynamic vs static
86
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
@TypeChecked
def myMethod() {
def myPets = ['Lassie', 'Skip']
List yourPets = ['Lassie', 'Skip']
}
shouldFail(CompilationFailedException) {
assertScript '''
@groovy.transform.TypeChecked
def yourMethod() {
List ourPets = new Date()
}
'''
}
Dynamic vs static
87
def adder = { a, b -> a + b }
assert adder(100, 200) == 300
assert adder('X', 'Y') == 'XY'
def myPets = ['Lassie', 'Skip']
List<String> yourPets = ['Lassie', 'Skip']
shouldFail(ClassCastException) {
List ourPets = new Date()
}
@TypeChecked
def myMethod() {
def myPets = ['Lassie', 'Skip']
List yourPets = ['Lassie', 'Skip']
}
shouldFail(CompilationFailedException) {
assertScript '''
@groovy.transform.TypeChecked
def yourMethod() {
List ourPets = new Date()
}
'''
}
Extensible
Inference
Extensible type checking
import groovy.transform.TypeChecked
import experimental.SprintfTypeChecker
@TypeChecked(extensions=SprintfTypeChecker)
void main() {
sprintf('%s will turn %d on %tF', 'John', new Date(), 21)
}
[Static type checking] - Parameter types didn't match types
expected from the format String:
For placeholder 2 [%d] expected 'int' but was 'java.util.Date'
For placeholder 3 [%tF] expected 'java.util.Date' but was 'int'
sprintf has an Object varargs parameter, hence not normally
amenable to further static checking but for constant Strings
we can do better using a custom type checking plugin.
Extensible type checking
import groovy.sql.Sql
import groovy.transform.TypeChecked
@TypeChecked(extensions='SQLExtension.groovy')
findAthletes(Sql sql) {
sql.eachRow('select * frm Athlete') { row -> println row }
}
SqlTC.groovy: 7: [Static type checking] - SQL query is not
valid: net.sf.jsqlparser.JSQLParserException
@ line 6, column 15.
sql.eachRow('select * frm Athlete') { row -> println row }
^
1 error
Static compilation
import groovy.transform.*
class Actor {
String firstName, lastName
@CompileStatic
String getFullName() { "$firstName $lastName" }
void makePeace() {
new AntBuilder().echo('Peace was never an option')
}
}
def magneto = new Actor(firstName: 'Ian', lastName: 'McKellen')
assert magneto.fullName == 'Ian McKellen'
magneto.makePeace()
Static compilation speed
0
5
10
15
20
25
30
Fibonacci micro-benchmark
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Dynamic strong typing
• Static type checking
• Extensible
• Type inference
• Metaprogramming
• Domain Specific Language support
• Ecosystem
• Community/Team
• Maximise duck-typing
• Minimise noise
• yet type inference
• Flexibility at runtime
• As strict as you want
when needed
• Fast when needed
Awesome
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Runtime
• Compile-time
• Macros
• Domain Specific Language support
• Ecosystem
• Community/Team
Runtime metaprogramming
• Add instance & static methods, constructors,
properties at runtime
• Intercept method/property access
• Catch missing methods, properties
• Used for dynamic builders, aspect-oriented
programming, test stubs, mocks & dummies
Awesome*
* Individual levels of awesomeness may vary
Runtime metaprogramming
• Adding methods at runtime
assert 'Hello'.reverse() == 'olleH'
String.metaClass.swapCase = { delegate.collect{
it in 'A'..'Z' ? it.toLowerCase() : it.toUpperCase()
}.join() }
assert 'Hello'.swapCase() == 'hELLO'
Runtime metaprogramming
• Intercepting methods
class Foo {
def one() { println "Called one()" }
def methodMissing(String name, params) {
println "Attempted $name($params)"
}
}
def f = new Foo()
f.one()
f.two()
f.three('Some Arg')
Called one()
Attempted two([])
Attempted three([Some Arg])
XML Parsing/GPath expressions
def xml = '''
<hosts>
<host name='MyHost'>
<service name='MyMicroService'/>
<service name='MyNanoService'/>
</host>
</hosts>
'''
def hosts = new XmlParser().parseText(xml)
assert hosts.host.service[0].@name=='MyMicroService'
def xml = '''
<hosts>
<host name='MyHost'>
<service name='MyMicroService'/>
<service name='MyNanoService'/>
</host>
</hosts>
'''
def hosts = new XmlParser().parseText(xml)
assert hosts.host.service[0].@name=='MyMicroService'
XML Parsing/GPath expressions
Compile-time metaprogramming
• Gives you the ability to change the language by augmenting the
compilation process
Awesome
Compile-time metaprogramming
• Modify the program
at compile-time
@ToString
class Person {
String first, last
}
println new Person(first: 'John',
last: 'Smith')
// => Person(John, Smith)
Compile-time metaprogramming
• Modify the program
at compile-time
class Person {
String first, last
String toString() {
"Person($first, $last)"
}
}
println new Person(first: 'John',
last: 'Smith')
// => Person(John, Smith)
Parsing Summary
public run()
...
L1
ALOAD 1
LDC 1
AALOAD
ALOAD 0
LDC "Howdy Y'all"
INVOKEINTERFACE callCurrent()
ARETURN
...
println "Howdy Y'all"
BlockStatement
-> ReturnStatement
-> MethodCallExpression
-> VariableExpression("this")
-> ConstantExpression("println")
-> ArgumentListExpression
-> ConstantExpression("Howdy Y'all")
MyScript.groovy
> groovy MyScript.groovy
> groovyc MyScript.groovy
> groovysh
> groovyConsole
• 9 phase compiler
– Early stages: read source code
and convert into a sparse syntax
tree
– Middle stages: iteratively build up
a more dense and information rich
version of the syntax tree
– Later stages: check the tree and
convert it into byte code/class files
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
Parsing Summary
Parsing - Early Stages
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
@ToString
class Greeter {
String message = "Howdy Y'all"
void greet() {
println message
}
}
ClassNode: Greeter
MethodNode: greet
Property: message
type: unresolved(String)
AnnotationNode:
ToString
type:
unresolved(ToString)
methods:
properties:
annotations:
BlockStatement
MethodCall:
this.println(message)
Parsing - Middle Stages
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
ClassNode: Greeter
MethodNode: greet
FieldNode: message
type: resolved(String)
methods:
fields:
constructors:
ConstructorNode
MethodNode:
getMessageMethodNode:
setMessageMethodNode: toString
MethodNode:
getMetaClass…
Parsing - Final Stages
106
Initialization
Semantic Analysis
Instruction Selection
Parsing
Conversion
Canonicalization
Class Generation
Output
Finalization
public greet()V
...
L1
...
ALOAD 0
GETFIELD Greeter.message
INVOKEINTERFACE callCurrent()
POP
...
Immutable Classes
• Some Rules
• Don’t provide mutators
• Ensure that no methods can
be overridden
o Easiest to make the class final
o Or use static factories & non-public
constructors
• Make all fields final
• Make all fields private
o Avoid even public immutable constants
• Ensure exclusive access to any mutable components
o Don’t leak internal references
o Defensive copying in and out
• Optionally provide equals and hashCode methods
• Optionally provide toString method
@Immutable...
• Java Immutable Class
• As per Joshua Bloch Effective Java
public final class Person {
private final String first;
private final String last;
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null)
? 0 : first.hashCode());
result = prime * result + ((last == null)
? 0 : last.hashCode());
return result;
}
public Person(String first, String last) {
this.first = first;
this.last = last;
}
// ...
// ...
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (last == null) {
if (other.last != null)
return false;
} else if (!last.equals(other.last))
return false;
return true;
}
@Override
public String toString() {
return "Person(first:" + first
+ ", last:" + last + ")";
}
}
...@Immutable...
public final class Person {
private final String first;
private final String last;
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null)
? 0 : first.hashCode());
result = prime * result + ((last == null)
? 0 : last.hashCode());
return result;
}
public Person(String first, String last) {
this.first = first;
this.last = last;
}
// ...
// ...
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (last == null) {
if (other.last != null)
return false;
} else if (!last.equals(other.last))
return false;
return true;
}
@Override
public String toString() {
return "Person(first:" + first
+ ", last:" + last + ")";
}
}
boilerplate• Java Immutable Class
• As per Joshua Bloch Effective Java
...@Immutable
@Immutable class Person {
String first, last
}
Awesome
With Macros (Groovy 2.5+)
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.expr.*
def ast = new ReturnStatement(
new ConstructorCallExpression(
ClassHelper.make(Date),
ArgumentListExpression.EMPTY_ARGUMENTS
)
)
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
Awesome
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.expr.*
def ast = new ReturnStatement(
new ConstructorCallExpression(
ClassHelper.make(Date),
ArgumentListExpression.EMPTY_ARGUMENTS
)
)
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
• Variations:
• Expressions, Statements, Classes
• Supports variable substitution,
specifying compilation phase
def ast = macro {
return new Date()
}
With Macros (Groovy 2.5+)
• AST Matching:
• Selective transformations, filtering, testing
• Supports placeholders
Expression transform(Expression exp) {
Expression ref = macro { 1 + 1 }
if (ASTMatcher.matches(ref, exp)) {
return macro { 2 }
}
return super.transform(exp)
}
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
def getName(Z z) {
z.y.list[0].name
}
• nullSafe
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
z.y.list[0].name
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
z.y.list[0].name
}
Prone to NPE
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
• nullSafe
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
def result = null
if (z != null && z.y != null &&
z.y.list != null && z.y.list[0] != null) {
result = z.y.list[0].name
}
result
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
Macro method examples
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
def getName(Z z) {
def result = null
if (z != null && z.y != null &&
z.y.list != null && z.y.list[0] != null) {
result = z.y.list[0].name
}
result
}
Verbose
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
Macro method examples
def getName(Z z) {
z?.y?.list?[0]?.name
}
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
class X {
String name
}
class Y {
List<X> list
}
class Z {
Y y
}
Macro method examples
Adapted from https://github.com/touchez-du-bois/akatsuki
but adapted for the experimental Antlr4 “Parrot” parser.
• nullSafe
def getName(Z z) {
nullSafe(z.y.list[0].name)
}
Macro method examples
@Macro
static Expression nullSafe(MacroContext macroContext, Expression expression) {
if (expression instanceof PropertyExpression) {
// exp.prop -> exp?.prop …
} else if (expression instanceof MethodCallExpression) {
// exp.method() -> exp?.method() …
}
return expression
}
• nullSafe
def getName(Z z) {
nullSafe(z.y.list[0].name)
}
Macro method examples
def fact(num) {
return match(num) {
when String then fact(num.toInteger())
when(0 | 1) then 1
when 2 then 2
orElse num * fact(num - 1)
}
}
assert fact("5") == 120
See: https://github.com/touchez-du-bois/akatsuki
Macro method examples
• Spock inspired
@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
import spock.lang.Specification
class MathSpec extends Specification {
def "maximum of two numbers"(int a, int b, int c) {
expect:
Math.max(a, b) == c
where:
a | b | c
1 | 3 | 3
7 | 4 | 7
0 | 0 | 0
}
}
Macro method examples
See: https://github.com/touchez-du-bois/akatsuki
doWithData {
dowith:
assert a + b == c
where:
a | b || c
1 | 2 || 3
4 | 5 || 9
7 | 8 || 15
}
What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Runtime
• Compile-time
• Macros
• Domain Specific Language support
• Ecosystem
• Community/Team
• Ability to change the language
at runtime
• Ability to change the language
during the compilation process
• Macros provide a
homogeneous form
for writing AST
transformations
Awesome
Part 2: What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
 Command chains
• Cranes and tortoises revisited
• Ecosystem
• Community/Team
Command Chains
• Ability to chain method calls without parentheses and dots
Awesome
Command Chains
• Ability to chain method calls without parentheses and dots
move forward at 3.km/h
Command Chains
• Ability to chain method calls without parentheses and dots
• Equivalent to:
move forward at 3.km/h
move(forward).at(3.getKm().div(h))
Command chains in DSLs
Number.metaClass.getShares = { delegate }
Number.metaClass.getDollars = { delegate }
String GOOG = 'Google'
def sell(int nShares) {
[of: { String ticker ->
[at: { int price ->
println "Sold $nShares $ticker at $$price"
}]
}]
}
sell 100.shares of GOOG at 1000.dollars
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please show the square_root of 100
// ==> 10.0
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please(show).the(square_root).of(100)
// ==> 10.0
Command chains in DSLs
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
please(show).the(square_root).of(100)
// ==> 10.0
… and again in another language …
Command chains in DSLs
// Japanese DSL
Object.metaClass.を =
Object.metaClass.の =
{ clos -> clos(delegate) }
まず = { it }
表示する = { println it }
平方根 = { Math.sqrt(it) }
まず 100 の 平方根 を 表示する
// First, show the square root of 100
// => 10.0 // source: http://d.hatena.ne.jp/uehaj/20100919/1284906117
// http://groovyconsole.appspot.com/edit/241001
Part 3: What makes Groovy Awesome?
• Java integration
• Scripting support
• Multiparadigm
• Gradual typing
• Metaprogramming
• Domain Specific Language support
• Command chains
 Cranes and tortoises revisited
• Ecosystem
• Community/Team
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
How many of each animal?
Recall: Constraint programming example
@Grab('org.choco-solver:choco-solver:4.0.0')
import org.chocosolver.solver.Model
def m = new Model()
def totalAnimals = 7
def totalLegs = 20
def numCranes = m.intVar('Cranes', 0, totalAnimals, true)
def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true)
def numCraneLegs = m.intScaleView(numCranes, 2)
def numTortoiseLegs = m.intScaleView(numTortoises, 4)
m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post()
m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post()
if (m.solver.solve())
println "$numCranesn$numTortoises"
else
println "No Solutions" Cranes = 4
Tortoises = 3
ChocoCraneTortoise.groovy
Logic programming example
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
cranes have 2 legs
tortoises have 4 legs
there are 7 animals
there are 20 legs
display solution
Cranes 4
Tortoises 3
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
cranes have 2 legs
tortoises have 4 legs
millipedes have 1000 legs
there are 8 animals
there are 1020 legs
display solution
Cranes 4
Tortoises 3
Millipedes 1
dslUntyped/ChocoCraneTortoiseDSL.groovy
50 lines to define the DSL
Logic programming example
Crane(2), Tortoise(4), Beetle(6), Centipede(100), Millipede(1000)
Solution: Tortoise = 3, Beetle = 23
Solution: Crane = 1, Tortoise = 1, Beetle = 24
Solution: Crane = 25, Centipede = 1
dslTyped/ChocoCraneTortoiseDSL.groovy
80 lines to define the DSL
@TypeChecked
def main() {
animals seen include Crane, Tortoise, Beetle, Centipede
leg count is 150
head count is 26
display solution
}
@TypeChecked
def main() {
animals seen include Crane, Tortoise, Beetle, Centipede
leg count is 150
head count is 26
display solution
}
Logic programming example
dslTyped/ChocoCraneTortoiseDSL.groovy
80 lines to define the DSL
DSL Type Provider
unresolvedVariable { var ->
if (!cachedAnimalNames) {
def accessKey = '72ddf45a-c751-44c7-9bca-8db3b4513347'
// for illustrative purposes, just download xml for a few animals
def uid = 'ELEMENT_GLOBAL.2.104550,ELEMENT_GLOBAL.2.105196,ELEMENT_GLOBAL.2.120227'
def base = "https://services.natureserve.org/idd/rest/ns/v1.1/globalSpecies"
def url = "$base/comprehensive?uid=$uid&NSAccessKeyId=$accessKey"
def root = new XmlParser().parse(url)
def names = root.globalSpecies.classification.names
cachedAnimalNames = names.natureServePrimaryGlobalCommonName*.text()*.replaceAll(' ','')
}
if (var.name in cachedAnimalNames) {
storeType(var, STRING_TYPE)
handled = true
enclosingClassNode.addField(var.name, 0, STRING_TYPE, new ConstantExpression(var.name))
}
}
DSL Type Provider
@TypeChecked(extensions='NatureServeAnimalProvider.groovy')
def main() {
animals seen include SandhillCrane, GopherTortoise, ChihuahuanMillipede
leg count is 1020
head count is 8
display solution
}
Custom checker
provider/ChocoCraneTortoiseProvider.groovy
80 lines to define the DSL
25 lines to define the provider
Awesome
Awesome
Awesome
Awesome
Ecosystem
Groovy's Awesome Team
Groovy's Awesome Team
Groovy's Awesome Team
+100's of others
Direct downloads:
2013: approx. 3 million
2014: 4+ million
2015: 12+ million
now: 2+ million/month
Groovy's Awesome Team
+100's of others just like YOU!
http://www.manning.com/koenig2
Groovy in Action 2nd edition
Manning promo code:
ctwg3sum
(39% off all Manning books)
152

More Related Content

What's hot

Sql Antipatterns Strike Back
Sql Antipatterns Strike BackSql Antipatterns Strike Back
Sql Antipatterns Strike Back
Karwin Software Solutions LLC
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss Forge
Antoine Sabot-Durand
 
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
YongSung Yoon
 
Lessons learned from operating Data Platform on Kubernetes(EKS)
Lessons learned from operating Data Platform on Kubernetes(EKS)Lessons learned from operating Data Platform on Kubernetes(EKS)
Lessons learned from operating Data Platform on Kubernetes(EKS)
창언 정
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
Debasish Ghosh
 
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
Spark Summit
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
if kakao
 
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
PgDay.Seoul
 
Implementing High Availability Caching with Memcached
Implementing High Availability Caching with MemcachedImplementing High Availability Caching with Memcached
Implementing High Availability Caching with Memcached
Gear6
 
Fully Utilizing Spark for Data Validation
Fully Utilizing Spark for Data ValidationFully Utilizing Spark for Data Validation
Fully Utilizing Spark for Data Validation
Databricks
 
Cache in API Gateway
Cache in API GatewayCache in API Gateway
Cache in API Gateway
GilWon Oh
 
Grafana introduction
Grafana introductionGrafana introduction
Grafana introduction
Rico Chen
 
Spring Cloud Workshop
Spring Cloud WorkshopSpring Cloud Workshop
Spring Cloud Workshop
YongSung Yoon
 
NoSQL panorama - Jean Seiler Softeam
NoSQL panorama - Jean Seiler SofteamNoSQL panorama - Jean Seiler Softeam
NoSQL panorama - Jean Seiler Softeam
TelecomValley
 
Tuning Slow Running SQLs in PostgreSQL
Tuning Slow Running SQLs in PostgreSQLTuning Slow Running SQLs in PostgreSQL
Tuning Slow Running SQLs in PostgreSQL
Ashnikbiz
 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keyword
Pham Huy Tung
 
ksqlDB로 실시간 데이터 변환 및 스트림 처리
ksqlDB로 실시간 데이터 변환 및 스트림 처리ksqlDB로 실시간 데이터 변환 및 스트림 처리
ksqlDB로 실시간 데이터 변환 및 스트림 처리
confluent
 
MySQL Scalability and Reliability for Replicated Environment
MySQL Scalability and Reliability for Replicated EnvironmentMySQL Scalability and Reliability for Replicated Environment
MySQL Scalability and Reliability for Replicated Environment
Jean-François Gagné
 
Grails Controllers
Grails ControllersGrails Controllers
Grails Controllers
NexThoughts Technologies
 
Glass fish performance tuning tips from the field
Glass fish performance tuning tips from the fieldGlass fish performance tuning tips from the field
Glass fish performance tuning tips from the field
Payara
 

What's hot (20)

Sql Antipatterns Strike Back
Sql Antipatterns Strike BackSql Antipatterns Strike Back
Sql Antipatterns Strike Back
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss Forge
 
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
 
Lessons learned from operating Data Platform on Kubernetes(EKS)
Lessons learned from operating Data Platform on Kubernetes(EKS)Lessons learned from operating Data Platform on Kubernetes(EKS)
Lessons learned from operating Data Platform on Kubernetes(EKS)
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
Cassandra and Spark: Optimizing for Data Locality-(Russell Spitzer, DataStax)
 
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
 
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
[pgday.Seoul 2022] PostgreSQL구조 - 윤성재
 
Implementing High Availability Caching with Memcached
Implementing High Availability Caching with MemcachedImplementing High Availability Caching with Memcached
Implementing High Availability Caching with Memcached
 
Fully Utilizing Spark for Data Validation
Fully Utilizing Spark for Data ValidationFully Utilizing Spark for Data Validation
Fully Utilizing Spark for Data Validation
 
Cache in API Gateway
Cache in API GatewayCache in API Gateway
Cache in API Gateway
 
Grafana introduction
Grafana introductionGrafana introduction
Grafana introduction
 
Spring Cloud Workshop
Spring Cloud WorkshopSpring Cloud Workshop
Spring Cloud Workshop
 
NoSQL panorama - Jean Seiler Softeam
NoSQL panorama - Jean Seiler SofteamNoSQL panorama - Jean Seiler Softeam
NoSQL panorama - Jean Seiler Softeam
 
Tuning Slow Running SQLs in PostgreSQL
Tuning Slow Running SQLs in PostgreSQLTuning Slow Running SQLs in PostgreSQL
Tuning Slow Running SQLs in PostgreSQL
 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keyword
 
ksqlDB로 실시간 데이터 변환 및 스트림 처리
ksqlDB로 실시간 데이터 변환 및 스트림 처리ksqlDB로 실시간 데이터 변환 및 스트림 처리
ksqlDB로 실시간 데이터 변환 및 스트림 처리
 
MySQL Scalability and Reliability for Replicated Environment
MySQL Scalability and Reliability for Replicated EnvironmentMySQL Scalability and Reliability for Replicated Environment
MySQL Scalability and Reliability for Replicated Environment
 
Grails Controllers
Grails ControllersGrails Controllers
Grails Controllers
 
Glass fish performance tuning tips from the field
Glass fish performance tuning tips from the fieldGlass fish performance tuning tips from the field
Glass fish performance tuning tips from the field
 

Viewers also liked

Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedAndres Almiray
 
groovy transforms
groovy transformsgroovy transforms
groovy transforms
Paul King
 
groovy databases
groovy databasesgroovy databases
groovy databases
Paul King
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy Tutorial
Paul King
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
Guillaume Laforge
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy Ecosystem
Andres Almiray
 
Making the Most of Your Gradle Build
Making the Most of Your Gradle BuildMaking the Most of Your Gradle Build
Making the Most of Your Gradle Build
Andres Almiray
 
Make Your Testing Groovy
Make Your Testing GroovyMake Your Testing Groovy
Make Your Testing Groovy
Paul King
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gparsPaul King
 
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g ImplementationsPractical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
Michael Rainey
 
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data WarehousingGoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
Michael Rainey
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
Michael Rainey
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data IntegrationA Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
Michael Rainey
 
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data StreamingOracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Michael Rainey
 
그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수
Yeon Soo Kim
 
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12cGoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
Michael Rainey
 
Real-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success StoriesReal-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success Stories
Michael Rainey
 
GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...
Michael Rainey
 
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c AdaptorsReal-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Michael Rainey
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVM
Massimiliano Dessì
 

Viewers also liked (20)

Gr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem RevisitedGr8conf - The Groovy Ecosystem Revisited
Gr8conf - The Groovy Ecosystem Revisited
 
groovy transforms
groovy transformsgroovy transforms
groovy transforms
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Groovy Tutorial
Groovy TutorialGroovy Tutorial
Groovy Tutorial
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
Greach - The Groovy Ecosystem
Greach - The Groovy EcosystemGreach - The Groovy Ecosystem
Greach - The Groovy Ecosystem
 
Making the Most of Your Gradle Build
Making the Most of Your Gradle BuildMaking the Most of Your Gradle Build
Making the Most of Your Gradle Build
 
Make Your Testing Groovy
Make Your Testing GroovyMake Your Testing Groovy
Make Your Testing Groovy
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gpars
 
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g ImplementationsPractical Tips for Oracle Business Intelligence Applications 11g Implementations
Practical Tips for Oracle Business Intelligence Applications 11g Implementations
 
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data WarehousingGoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
GoldenGate and ODI - A Perfect Match for Real-Time Data Warehousing
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration - Coll...
 
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data IntegrationA Walk Through the Kimball ETL Subsystems with Oracle Data Integration
A Walk Through the Kimball ETL Subsystems with Oracle Data Integration
 
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data StreamingOracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
 
그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수그루비 소개 발표자료 - 김연수
그루비 소개 발표자료 - 김연수
 
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12cGoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
GoldenGate and Oracle Data Integrator - A Perfect Match- Upgrade to 12c
 
Real-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success StoriesReal-time Data Warehouse Upgrade – Success Stories
Real-time Data Warehouse Upgrade – Success Stories
 
GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...GoldenGate and Oracle Data Integrator - A Perfect Match...
GoldenGate and Oracle Data Integrator - A Perfect Match...
 
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c AdaptorsReal-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
Real-Time Data Replication to Hadoop using GoldenGate 12c Adaptors
 
Vert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVMVert.X like Node.js but polyglot and reactive on JVM
Vert.X like Node.js but polyglot and reactive on JVM
 

Similar to awesome groovy

groovy rules
groovy rulesgroovy rules
groovy rulesPaul King
 
Groovy
GroovyGroovy
Einführung in TypeScript
Einführung in TypeScriptEinführung in TypeScript
Einführung in TypeScript
Demian Holderegger
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
loffenauer
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
Maarten Balliauw
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
Paul King
 
Introduction to Oracle Groovy
Introduction to Oracle GroovyIntroduction to Oracle Groovy
Introduction to Oracle Groovy
Deepak Bhagat
 
Polyglot Programming in the JVM
Polyglot Programming in the JVMPolyglot Programming in the JVM
Polyglot Programming in the JVMAndres Almiray
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
Garth Gilmour
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
CiaranMcNulty
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
Jonathan Felch
 
Top 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdetTop 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdet
DevLabs Alliance
 
Writing Groovy DSLs
Writing Groovy DSLsWriting Groovy DSLs
Writing Groovy DSLs
adam1davis
 
Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Andres Almiray
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
Peter Maas
 
The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)
jaxLondonConference
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
Tugdual Grall
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java Developers
Andres Almiray
 
Groovy
GroovyGroovy
Groovy
atonse
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystem
Kostas Saidis
 

Similar to awesome groovy (20)

groovy rules
groovy rulesgroovy rules
groovy rules
 
Groovy
GroovyGroovy
Groovy
 
Einführung in TypeScript
Einführung in TypeScriptEinführung in TypeScript
Einführung in TypeScript
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
 
Introduction to Oracle Groovy
Introduction to Oracle GroovyIntroduction to Oracle Groovy
Introduction to Oracle Groovy
 
Polyglot Programming in the JVM
Polyglot Programming in the JVMPolyglot Programming in the JVM
Polyglot Programming in the JVM
 
The Great Scala Makeover
The Great Scala MakeoverThe Great Scala Makeover
The Great Scala Makeover
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
 
Top 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdetTop 20 java programming interview questions for sdet
Top 20 java programming interview questions for sdet
 
Writing Groovy DSLs
Writing Groovy DSLsWriting Groovy DSLs
Writing Groovy DSLs
 
Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010Polyglot Programming @ Jax.de 2010
Polyglot Programming @ Jax.de 2010
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Groovy for Java Developers
Groovy for Java DevelopersGroovy for Java Developers
Groovy for Java Developers
 
Groovy
GroovyGroovy
Groovy
 
Apache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystemApache Groovy: the language and the ecosystem
Apache Groovy: the language and the ecosystem
 

More from Paul King

tictactoe groovy
tictactoe groovytictactoe groovy
tictactoe groovy
Paul King
 
functional groovy
functional groovyfunctional groovy
functional groovyPaul King
 
Make Testing Groovy
Make Testing GroovyMake Testing Groovy
Make Testing Groovy
Paul King
 
Agile Testing Practices
Agile Testing PracticesAgile Testing Practices
Agile Testing Practices
Paul King
 
groovy DSLs from beginner to expert
groovy DSLs from beginner to expertgroovy DSLs from beginner to expert
groovy DSLs from beginner to expert
Paul King
 
groovy and concurrency
groovy and concurrencygroovy and concurrency
groovy and concurrency
Paul King
 
GroovyDSLs
GroovyDSLsGroovyDSLs
GroovyDSLs
Paul King
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
Paul King
 
Dynamic Language Practices
Dynamic Language PracticesDynamic Language Practices
Dynamic Language Practices
Paul King
 
Make Your Builds More Groovy
Make Your Builds More GroovyMake Your Builds More Groovy
Make Your Builds More Groovy
Paul King
 
Groovy Power Features
Groovy Power FeaturesGroovy Power Features
Groovy Power Features
Paul King
 
Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009
Paul King
 
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...Paul King
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Paul King
 
XML and Web Services with Groovy
XML and Web Services with GroovyXML and Web Services with Groovy
XML and Web Services with Groovy
Paul King
 

More from Paul King (15)

tictactoe groovy
tictactoe groovytictactoe groovy
tictactoe groovy
 
functional groovy
functional groovyfunctional groovy
functional groovy
 
Make Testing Groovy
Make Testing GroovyMake Testing Groovy
Make Testing Groovy
 
Agile Testing Practices
Agile Testing PracticesAgile Testing Practices
Agile Testing Practices
 
groovy DSLs from beginner to expert
groovy DSLs from beginner to expertgroovy DSLs from beginner to expert
groovy DSLs from beginner to expert
 
groovy and concurrency
groovy and concurrencygroovy and concurrency
groovy and concurrency
 
GroovyDSLs
GroovyDSLsGroovyDSLs
GroovyDSLs
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Dynamic Language Practices
Dynamic Language PracticesDynamic Language Practices
Dynamic Language Practices
 
Make Your Builds More Groovy
Make Your Builds More GroovyMake Your Builds More Groovy
Make Your Builds More Groovy
 
Groovy Power Features
Groovy Power FeaturesGroovy Power Features
Groovy Power Features
 
Groovy Testing Sep2009
Groovy Testing Sep2009Groovy Testing Sep2009
Groovy Testing Sep2009
 
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...Craig Smith & Paul King   Agile Tool Hacking   Taking Your Agile Development ...
Craig Smith & Paul King Agile Tool Hacking Taking Your Agile Development ...
 
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
Industrial Strength Groovy - Tools for the Professional Groovy Developer: Pau...
 
XML and Web Services with Groovy
XML and Web Services with GroovyXML and Web Services with Groovy
XML and Web Services with Groovy
 

Recently uploaded

Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
MayankTawar1
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
Jelle | Nordend
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
Sharepoint Designs
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
kalichargn70th171
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
XfilesPro
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
NaapbooksPrivateLimi
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 

Recently uploaded (20)

Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024Explore Modern SharePoint Templates for 2024
Explore Modern SharePoint Templates for 2024
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
A Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdfA Comprehensive Look at Generative AI in Retail App Testing.pdf
A Comprehensive Look at Generative AI in Retail App Testing.pdf
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 

awesome groovy

  • 1. Dr Paul King Groovy Lead for Object Computing Inc. @paulk_asert http:/slideshare.net/paulk_asert/awesome-groovy https://github.com/paulk-asert/awesome-groovy Apache Groovy: The Awesome Parts FRIEND OF GROOVY
  • 2.
  • 4. What is Groovy? 4 Groovy = Java – boiler plate code + closures (1st class FP) + extensible type system + runtime & compile-time metaprogramming + flexible language grammar (DSLs) + scripting + GDK library “Groovy is like a super version of Java. It leverages Java features but adds productivity features and provides great flexibility and extensibility.”
  • 5.
  • 7. Why Groovy? Too verbose Support functional programming Better concurrency Evolves too slowly I need feature XXX Too complex for some situations More flexibility Java
  • 8. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting
  • 9. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Java integration
  • 10. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Good IDE support Java integration
  • 11. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Good IDE support Custom features Java integration
  • 12. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Support concurrency Good IDE support Custom features Java integration
  • 13. Why Groovy? Groovy Make it simplerMake it dynamic Support simple scripting Support functional style Support concurrency Good IDE support Custom features Java integration
  • 14.
  • 15. Java code for list manipulation import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } }
  • 16. Groovy code for list manipulation import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Rename Main.java to Main.groovy
  • 17. Some Java Boilerplate identified import java.util.List; import java.util.ArrayList; class Main { private List keepShorterThan(List strings, int length) { List result = new ArrayList(); for (int i = 0; i < strings.size(); i++) { String s = (String) strings.get(i); if (s.length() < length) { result.add(s); } } return result; } public static void main(String[] args) { List names = new ArrayList(); names.add("Ted"); names.add("Fred"); names.add("Jed"); names.add("Ned"); System.out.println(names); Main m = new Main(); List shortNames = m.keepShorterThan(names, 4); System.out.println(shortNames.size()); for (int i = 0; i < shortNames.size(); i++) { String s = (String) shortNames.get(i); System.out.println(s); } } } Are the semicolons needed? And shouldn’t we us more modern list notation? Why not import common libraries? Do we need the static types? Must we always have a main method and class definition? How about improved consistency?
  • 18. Java Boilerplate removed def keepShorterThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() < length) { result.add(s) } } return result } names = new ArrayList() names.add("Ted"); names.add("Fred") names.add("Jed"); names.add("Ned") System.out.println(names) shortNames = keepShorterThan(names, 4) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) }
  • 19. More Java Boilerplate identified def keepShorterThan(strings, length) { def result = new ArrayList() for (s in strings) { if (s.size() < length) { result.add(s) } } return result } names = new ArrayList() names.add("Ted"); names.add("Fred") names.add("Jed"); names.add("Ned") System.out.println(names) shortNames = keepShorterThan(names, 4) System.out.println(shortNames.size()) for (s in shortNames) { System.out.println(s) } Shouldn’t we have special notation for lists? And special facilities for list processing? Is ‘return’ needed at end? Is the method now needed? Simplify common methods? Remove unambiguous brackets?
  • 20. Boilerplate removed = nicer Groovy version names = ["Ted", "Fred", "Jed", "Ned"] println names shortNames = names.findAll{ it.size() < 4 } println shortNames.size() shortNames.each{ println it } ["Ted", "Fred", "Jed", "Ned"] 3 Ted Jed Ned Output:
  • 21. Or Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 // plus a DSL implementation
  • 22. Or Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 names = [] def of, having, less def given(_the) { [names:{ Object[] ns -> names.addAll(ns) [and: { n -> names += n }] }] } def the = [ number: { _of -> [names: { _having -> [size: { _less -> [than: { size -> println names.findAll{ it.size() < size }.size() }]}] }] }, names: { _having -> [size: { _less -> [than: { size -> names.findAll{ it.size() < size }.each{ println it } }]}] } ] def all = [the: { println it }] def display(arg) { arg }
  • 23. Or Groovy DSL version if required • Or use GDSL (IntelliJ IDEA) or DSLD (Eclipse) given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4
  • 24. Or typed Groovy DSL version if required given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 … enum The { the } enum Having { having } enum Of { of } … class DisplayThe { DisplayTheNamesHaving names(Having having) { new DisplayTheNamesHaving() } DisplayTheNumberOf number(Of of) { new DisplayTheNumberOf() } } … // plus 50 lines
  • 25. Or typed Groovy DSL version if required
  • 26. Groovy DSL being debugged
  • 27. Or typed Groovy DSL version if required @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 }
  • 28. Or typed Groovy DSL version if required @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } 
  • 29. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", "Fred", "Jed" and "Ned" display all the names display the number of names having size less than 4 display the names having size less than 4 } Or typed Groovy DSL version if required afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } }
  • 30. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", “Mary", "Jed" and “Pete" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } Or typed Groovy DSL version if required
  • 31. @TypeChecked(extensions='EdChecker.groovy') def method() { given the names "Ted", “Mary", "Jed" and “Pete" display all the names display the number of names having size less than 4 display the names having size less than 4 } afterMethodCall { mc -> mc.arguments.each { if (isConstantExpression(it)) { if (it.value instanceof String && !it.value.endsWith('ed')) { addStaticTypeError("I don't like the name '${it.value}'", mc) } } } } Or typed Groovy DSL version if required 
  • 32. What style of language is Groovy?
  • 33. Groovy Style • Imperative/OO but somewhat paradigm agnostic •Dynamic, optionally static (gradual extensible typing) • Extensible language features through metaprogramming
  • 34. Part 2: What makes Groovy Awesome?
  • 35. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain specific language (DSL) support • Ecosystem • Community/Team Awesome
  • 36. What makes Groovy Awesome? • Java integration • Builds up on Java • Tight integration • Polyglot friendly • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 37. Java Integration • Groovy is Java’s friend Java Groovy
  • 38. Java Integration • Standing on the shoulders of Giants • Some limitations inherited but much gained through new releases of Java • Rock solid foundation • Can ease migration to new versions of Java Java Groovy
  • 39. Java Integration • Seamless integration • IDEs provide cross-language compile, navigation, and refactoring • Arbitrarily mix source language • Drop-in replace any class • Overloaded methods • Syntax alignment • Shared data types Java Groovy
  • 40. Java Integration • Seamless integration • IDEs provide cross-language compile, navigation, and refactoring • Arbitrarily mix source language • Drop-in replace any class • Overloaded methods • Syntax alignment • Shared data types Java Groovy
  • 41. Java Integration • Polyglot friendly • Typically integrates well with other languages which integrate with Java • JRuby • Jython • Scala • Frege • Clojure • R through Renjin • JavaScript (Rhino/Nashorn)
  • 42. Java Integration • Polyglot friendly • JSR-223 scripting to talk to JavaScript import javax.script.ScriptEngineManager def mgr = new ScriptEngineManager() def engine = mgr.getEngineByName('nashorn') assert engine.eval(''' function factorial(n) { if (n == 0) { return 1; } return n * factorial(n - 1); } factorial(4) ''') == 24.0 Java GroovyJavaScript
  • 43. Java Integration • Polyglot friendly: R integration @GrabResolver('https://nexus.bedatadriven.com/content/groups/public') @Grab('org.renjin:renjin-script-engine:0.7.0-RC7') import javax.script.ScriptEngineManager def mgr = new ScriptEngineManager() def engine = mgr.getEngineByName('Renjin') engine.with { eval ''' factorial <- function(x) { y <- 1 for (i in 1:x) { y <- y * i } return(y) } ''' assert eval('factorial(4)')[0] == 24 } Java GroovyR
  • 44. Grooscript @Grab('org.grooscript:grooscript:1.2.0') import org.grooscript.GrooScript import javax.script.ScriptEngineManager def groojs = GrooScript.convert ''' def sayHello = { println "Hello ${it}!" } ['Groovy','JavaScript','GrooScript'].each sayHello''', [initialText: 'var console = { log: print }', addGsLib: 'grooscript.min'] new ScriptEngineManager().getEngineByName("nashorn").eval(groojs) Hello Groovy! Hello JavaScript! Hello GrooScript! Jorge Franco, grooscript.org Convert Groovy subset to JavaScript Support: Gradle, Grails, NPM Demos: react.js, node.js, Pollock Converts: Classes, closures, Date primitives, ranges, String/GString Special: builder, templates, gQuery
  • 45. What makes Groovy Awesome? • Java integration • Builds up on Java • Tight integration • Polyglot friendly • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome • Friend of Java • Integration • Good JVM Citizen
  • 46. What makes Groovy Awesome? • Java integration • Scripting support • Simplified scripting • Separation of concerns • Security sandbox • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome
  • 47. Scripting • Terse format • Isolation • Domain-Specific Languages (DSLs) • Security • Flexibility
  • 48. Scripting • Leave out surrounding class • Entire source file: public class Script { public static void main(String[] args) { System.out.println("Hello world"); } } println "Hello world"
  • 49. Scripting • Various approaches supported • GroovyShell • GroovyScriptEngine • GroovyClassLoader • Spring • JSR-223 • Base scripts • allows predefined methods • Binding • allows predefined variables • Customizers • add imports, static imports • lock down AST to a subset • apply any AST transform transparently
  • 53. Scripting class Robot { void move(dir) { println "robot moved $dir" } } def robot = new Robot()
  • 54. Scripting import static Direction.* enum Direction { left, right, forward, backward } class Robot { void move(Direction dir) { println "robot moved $dir" } } def robot = new Robot() robot.move left
  • 55. Scripting move left def robot = new Robot() def binding = new Binding( robot: robot, move: robot.&move, *: Direction.values().collectEntries { [(it.name()): it] } ) def shell = new GroovyShell(binding) shell.evaluate new File(args[0]).text
  • 56. Scripting move left def robot = new Robot() def binding = new Binding(/* ... */) def imports = new ImportCustomizer().addStaticStars('java.lang.Math') def timeout = new ASTTransformationCustomizer(value: 2, TimedInterrupt) def secure = new SecureASTCustomizer().with { closuresAllowed = false importsWhitelist = [] tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, /*...*/ ] //... } def sysExit = new CompilationCustomizer(CANONICALIZATION) { void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) { new ClassCodeVisitorSupport() { void visitMethodCallExpression(MethodCallExpression call) { // check for System.exit() } // ... }.visitClass(cn) } } def config = new CompilerConfiguration() config.addCompilationCustomizers(imports, timeout, secure, sysExit) def shell = new GroovyShell(binding, config)
  • 57. Scripting move left move forward at 3.km/h More examples later
  • 58. What makes Groovy Awesome? • Java integration • Scripting support • Simplified scripting • Separation of concerns • Security sandbox • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team Awesome • Simpler scripting • Separation of concerns
  • 59. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Object-oriented • Functional, Closures • Logic/Dataflow programming • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 60. Multiparadigm • Imperative roots from Java • OO abstractions: classes, interfaces, inheritance • Properties • Traits • First class functional support via closures • External libraries for advanced features • Other paradigms via libraries • Logic, dataflow, reactive Awesome
  • 62. Rich OO features • Classes (and scripts, GroovyBeans) • Fields (and properties) • Methods, constructors, multi-methods, named and default parameters • Inheritance (behavior and implementation), interfaces, traits • Type aliases • Packages • Special accessor notation, spread operators, GPath, safe navigation
  • 63. Traits /** * Things that hop * @author Grace */ trait Hopper { String jump() { "I'm jumping!" } } class Kangaroo implements Hopper {} def skip = new Kangaroo() assert skip.jump() == "I'm jumping!"
  • 64. Rich functional features • Closures • First-class functions • Higher-order functions • Map, reduce, filter • Mutable & immutable data • Recursion • Lazy & eager evaluation • Advanced FP techniques • Memoization, Trampolines, Composition, Curry • Concurrency
  • 65. map/filter/reduce @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL'
  • 66. map/filter/reduce (+ functional style) @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL' def young = { person, threshold -> person.age < threshold }.rcurry(40).memoize() assert people .findAll(young) .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL'
  • 67. map/filter/reduce (+ with streams) @Canonical class Person { String name int age } def people = [ new Person('Peter', 45), new Person('Paul', 35), new Person('Mary', 25) ] assert people .findAll{ it.age < 40 } .collect{ it.name.toUpperCase() } .sort() .join(', ') == 'MARY, PAUL' // requires JRE 8 def commaSep = Collectors.joining(", ") assert people.stream() .filter{ it.age < 40 } .map{ it.name.toUpperCase() } .sorted() .collect(commaSep) == 'MARY, PAUL'
  • 68. Logic/Constraint programming • Logic programming • Declarative style • Logic clauses for example Prolog • Constraint programming • Declarative style similar to logic programming but contain constraints which must be satisfied • Relations between variables are stated as constraints • Not a step or sequence of steps to execute, but rather the properties of a solution to be found
  • 69. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs How many of each animal?
  • 70. Constraint programming example @Grab('org.choco-solver:choco-solver:4.0.4') import org.chocosolver.solver.Model def m = new Model() def totalAnimals = 7 def totalLegs = 20 def numCranes = m.intVar('Cranes', 0, totalAnimals, true) def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true) def numCraneLegs = m.intScaleView(numCranes, 2) def numTortoiseLegs = m.intScaleView(numTortoises, 4) m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post() m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post() if (m.solver.solve()) println "$numCranesn$numTortoises" else println "No Solutions" Cranes = 4 Tortoises = 3 ChocoCraneTortoise.groovy See also: JSR-331 Constraint Programming API
  • 71. Dataflow programming • Declarative style • Emphasizes the movement of data • models programs as a series of connected tasks • A task has explicitly defined inputs and outputs • runs as soon as all of its inputs become available • Inherently parallel
  • 72. GPars • Library classes and DSL allowing you to handle tasks concurrently: • Data Parallelism map, filter, reduce functionality in parallel with parallel array support • Asynchronous functions extend the Java executor services to enable multi-threaded closure processing • Dataflow Concurrency supports natural shared-memory concurrency model, using single-assignment variables • Actors provide Erlang/Scala-like actors including "remote" actors on other machines • Safe Agents provide a non-blocking mt-safe reference to mutable state; like "agents" in Clojure 72 Awesome
  • 73. Concurrency challenge • We can analyse the example’s task graph: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] def a = 5 def b = f1(a) def c = f2(a) def d = f3(c) def f = f4(b, d) assert f == 10
  • 74. Concurrency challenge • We can analyse the example’s task graph: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] def a = 5 def b = f1(a) def c = f2(a) def d = f3(c) def f = f4(b, d) assert f == 10 f2 f3 f1 f4 aa b c d f
  • 75. Concurrency challenge • Manually using asynchronous functions: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import static groovyx.gpars.GParsPool.withPool withPool(2) { def a = 5 def futureB = f1.callAsync(a) def c = f2(a) def d = f3(c) def f = f4(futureB.get(), d) assert f == 10 } f2 f3 f1 f4 aa futureB c d f
  • 76. Concurrency challenge • And with GPars Dataflows: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import groovyx.gpars.dataflow.Dataflows import static groovyx.gpars.dataflow.Dataflow.task new Dataflows().with { task { a = 5 } task { b = f1(a) } task { c = f2(a) } task { d = f3(c) } task { f = f4(b, d) } assert f == 10 } f2 f3 f1 f4 aa b c d f
  • 77. Concurrency challenge • And with GPars Dataflows: def (f1, f2, f3, f4) = [{ sleep 1000; it }] * 3 + [{ x, y -> x + y }] import groovyx.gpars.dataflow.Dataflows import static groovyx.gpars.dataflow.Dataflow.task new Dataflows().with { task { f = f4(b, d) } task { d = f3(c) } task { c = f2(a) } task { b = f1(a) } task { a = 5 } assert f == 10 } f2 f3 f1 f4 aa b c d f
  • 78. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Object-oriented • Functional, Closures • Logic/dataflow programming • Gradual typing • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team • Ability to use imperative when needed for speed • Numerous declarative approaches available when it makes sense Awesome
  • 79. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Dynamic strong typing • Static type checking • Extensible • Type inference • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team
  • 80. Gradual typing • Dynamic by default • Gradual typing • Static type checking • Extensible type system Awesome
  • 81. Dynamic vs static 82 def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() }
  • 82. Dynamic vs static 83 Gradual Type-time? def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() }
  • 83. Dynamic vs static 84 def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY'
  • 84. Dynamic vs static 85 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } Duck-typing
  • 85. Dynamic vs static 86 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } @TypeChecked def myMethod() { def myPets = ['Lassie', 'Skip'] List yourPets = ['Lassie', 'Skip'] } shouldFail(CompilationFailedException) { assertScript ''' @groovy.transform.TypeChecked def yourMethod() { List ourPets = new Date() } ''' }
  • 86. Dynamic vs static 87 def adder = { a, b -> a + b } assert adder(100, 200) == 300 assert adder('X', 'Y') == 'XY' def myPets = ['Lassie', 'Skip'] List<String> yourPets = ['Lassie', 'Skip'] shouldFail(ClassCastException) { List ourPets = new Date() } @TypeChecked def myMethod() { def myPets = ['Lassie', 'Skip'] List yourPets = ['Lassie', 'Skip'] } shouldFail(CompilationFailedException) { assertScript ''' @groovy.transform.TypeChecked def yourMethod() { List ourPets = new Date() } ''' } Extensible Inference
  • 87. Extensible type checking import groovy.transform.TypeChecked import experimental.SprintfTypeChecker @TypeChecked(extensions=SprintfTypeChecker) void main() { sprintf('%s will turn %d on %tF', 'John', new Date(), 21) } [Static type checking] - Parameter types didn't match types expected from the format String: For placeholder 2 [%d] expected 'int' but was 'java.util.Date' For placeholder 3 [%tF] expected 'java.util.Date' but was 'int' sprintf has an Object varargs parameter, hence not normally amenable to further static checking but for constant Strings we can do better using a custom type checking plugin.
  • 88. Extensible type checking import groovy.sql.Sql import groovy.transform.TypeChecked @TypeChecked(extensions='SQLExtension.groovy') findAthletes(Sql sql) { sql.eachRow('select * frm Athlete') { row -> println row } } SqlTC.groovy: 7: [Static type checking] - SQL query is not valid: net.sf.jsqlparser.JSQLParserException @ line 6, column 15. sql.eachRow('select * frm Athlete') { row -> println row } ^ 1 error
  • 89. Static compilation import groovy.transform.* class Actor { String firstName, lastName @CompileStatic String getFullName() { "$firstName $lastName" } void makePeace() { new AntBuilder().echo('Peace was never an option') } } def magneto = new Actor(firstName: 'Ian', lastName: 'McKellen') assert magneto.fullName == 'Ian McKellen' magneto.makePeace()
  • 91. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Dynamic strong typing • Static type checking • Extensible • Type inference • Metaprogramming • Domain Specific Language support • Ecosystem • Community/Team • Maximise duck-typing • Minimise noise • yet type inference • Flexibility at runtime • As strict as you want when needed • Fast when needed Awesome
  • 92. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Runtime • Compile-time • Macros • Domain Specific Language support • Ecosystem • Community/Team
  • 93. Runtime metaprogramming • Add instance & static methods, constructors, properties at runtime • Intercept method/property access • Catch missing methods, properties • Used for dynamic builders, aspect-oriented programming, test stubs, mocks & dummies Awesome* * Individual levels of awesomeness may vary
  • 94. Runtime metaprogramming • Adding methods at runtime assert 'Hello'.reverse() == 'olleH' String.metaClass.swapCase = { delegate.collect{ it in 'A'..'Z' ? it.toLowerCase() : it.toUpperCase() }.join() } assert 'Hello'.swapCase() == 'hELLO'
  • 95. Runtime metaprogramming • Intercepting methods class Foo { def one() { println "Called one()" } def methodMissing(String name, params) { println "Attempted $name($params)" } } def f = new Foo() f.one() f.two() f.three('Some Arg') Called one() Attempted two([]) Attempted three([Some Arg])
  • 96. XML Parsing/GPath expressions def xml = ''' <hosts> <host name='MyHost'> <service name='MyMicroService'/> <service name='MyNanoService'/> </host> </hosts> ''' def hosts = new XmlParser().parseText(xml) assert hosts.host.service[0].@name=='MyMicroService'
  • 97. def xml = ''' <hosts> <host name='MyHost'> <service name='MyMicroService'/> <service name='MyNanoService'/> </host> </hosts> ''' def hosts = new XmlParser().parseText(xml) assert hosts.host.service[0].@name=='MyMicroService' XML Parsing/GPath expressions
  • 98. Compile-time metaprogramming • Gives you the ability to change the language by augmenting the compilation process Awesome
  • 99. Compile-time metaprogramming • Modify the program at compile-time @ToString class Person { String first, last } println new Person(first: 'John', last: 'Smith') // => Person(John, Smith)
  • 100. Compile-time metaprogramming • Modify the program at compile-time class Person { String first, last String toString() { "Person($first, $last)" } } println new Person(first: 'John', last: 'Smith') // => Person(John, Smith)
  • 101. Parsing Summary public run() ... L1 ALOAD 1 LDC 1 AALOAD ALOAD 0 LDC "Howdy Y'all" INVOKEINTERFACE callCurrent() ARETURN ... println "Howdy Y'all" BlockStatement -> ReturnStatement -> MethodCallExpression -> VariableExpression("this") -> ConstantExpression("println") -> ArgumentListExpression -> ConstantExpression("Howdy Y'all") MyScript.groovy > groovy MyScript.groovy > groovyc MyScript.groovy > groovysh > groovyConsole
  • 102. • 9 phase compiler – Early stages: read source code and convert into a sparse syntax tree – Middle stages: iteratively build up a more dense and information rich version of the syntax tree – Later stages: check the tree and convert it into byte code/class files Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization Parsing Summary
  • 103. Parsing - Early Stages Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization @ToString class Greeter { String message = "Howdy Y'all" void greet() { println message } } ClassNode: Greeter MethodNode: greet Property: message type: unresolved(String) AnnotationNode: ToString type: unresolved(ToString) methods: properties: annotations: BlockStatement MethodCall: this.println(message)
  • 104. Parsing - Middle Stages Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization ClassNode: Greeter MethodNode: greet FieldNode: message type: resolved(String) methods: fields: constructors: ConstructorNode MethodNode: getMessageMethodNode: setMessageMethodNode: toString MethodNode: getMetaClass…
  • 105. Parsing - Final Stages 106 Initialization Semantic Analysis Instruction Selection Parsing Conversion Canonicalization Class Generation Output Finalization public greet()V ... L1 ... ALOAD 0 GETFIELD Greeter.message INVOKEINTERFACE callCurrent() POP ...
  • 106. Immutable Classes • Some Rules • Don’t provide mutators • Ensure that no methods can be overridden o Easiest to make the class final o Or use static factories & non-public constructors • Make all fields final • Make all fields private o Avoid even public immutable constants • Ensure exclusive access to any mutable components o Don’t leak internal references o Defensive copying in and out • Optionally provide equals and hashCode methods • Optionally provide toString method
  • 107. @Immutable... • Java Immutable Class • As per Joshua Bloch Effective Java public final class Person { private final String first; private final String last; public String getFirst() { return first; } public String getLast() { return last; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; } public Person(String first, String last) { this.first = first; this.last = last; } // ... // ... @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; return true; } @Override public String toString() { return "Person(first:" + first + ", last:" + last + ")"; } }
  • 108. ...@Immutable... public final class Person { private final String first; private final String last; public String getFirst() { return first; } public String getLast() { return last; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); return result; } public Person(String first, String last) { this.first = first; this.last = last; } // ... // ... @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; return true; } @Override public String toString() { return "Person(first:" + first + ", last:" + last + ")"; } } boilerplate• Java Immutable Class • As per Joshua Bloch Effective Java
  • 109. ...@Immutable @Immutable class Person { String first, last } Awesome
  • 110. With Macros (Groovy 2.5+) import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.stmt.* import org.codehaus.groovy.ast.expr.* def ast = new ReturnStatement( new ConstructorCallExpression( ClassHelper.make(Date), ArgumentListExpression.EMPTY_ARGUMENTS ) ) def ast = macro { return new Date() }
  • 111. With Macros (Groovy 2.5+) Awesome import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.stmt.* import org.codehaus.groovy.ast.expr.* def ast = new ReturnStatement( new ConstructorCallExpression( ClassHelper.make(Date), ArgumentListExpression.EMPTY_ARGUMENTS ) ) def ast = macro { return new Date() }
  • 112. With Macros (Groovy 2.5+) • Variations: • Expressions, Statements, Classes • Supports variable substitution, specifying compilation phase def ast = macro { return new Date() }
  • 113. With Macros (Groovy 2.5+) • AST Matching: • Selective transformations, filtering, testing • Supports placeholders Expression transform(Expression exp) { Expression ref = macro { 1 + 1 } if (ASTMatcher.matches(ref, exp)) { return macro { 2 } } return super.transform(exp) }
  • 114. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. def getName(Z z) { z.y.list[0].name } • nullSafe
  • 115. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { z.y.list[0].name } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 116. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { z.y.list[0].name } Prone to NPE Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 117. Macro method examples • nullSafe class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { def result = null if (z != null && z.y != null && z.y.list != null && z.y.list[0] != null) { result = z.y.list[0].name } result } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser.
  • 118. Macro method examples class X { String name } class Y { List<X> list } class Z { Y y } def getName(Z z) { def result = null if (z != null && z.y != null && z.y.list != null && z.y.list[0] != null) { result = z.y.list[0].name } result } Verbose Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 119. Macro method examples def getName(Z z) { z?.y?.list?[0]?.name } class X { String name } class Y { List<X> list } class Z { Y y } Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe
  • 120. class X { String name } class Y { List<X> list } class Z { Y y } Macro method examples Adapted from https://github.com/touchez-du-bois/akatsuki but adapted for the experimental Antlr4 “Parrot” parser. • nullSafe def getName(Z z) { nullSafe(z.y.list[0].name) }
  • 121. Macro method examples @Macro static Expression nullSafe(MacroContext macroContext, Expression expression) { if (expression instanceof PropertyExpression) { // exp.prop -> exp?.prop … } else if (expression instanceof MethodCallExpression) { // exp.method() -> exp?.method() … } return expression } • nullSafe def getName(Z z) { nullSafe(z.y.list[0].name) }
  • 122. Macro method examples def fact(num) { return match(num) { when String then fact(num.toInteger()) when(0 | 1) then 1 when 2 then 2 orElse num * fact(num - 1) } } assert fact("5") == 120 See: https://github.com/touchez-du-bois/akatsuki
  • 123. Macro method examples • Spock inspired @Grab('org.spockframework:spock-core:1.0-groovy-2.4') import spock.lang.Specification class MathSpec extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c where: a | b | c 1 | 3 | 3 7 | 4 | 7 0 | 0 | 0 } }
  • 124. Macro method examples See: https://github.com/touchez-du-bois/akatsuki doWithData { dowith: assert a + b == c where: a | b || c 1 | 2 || 3 4 | 5 || 9 7 | 8 || 15 }
  • 125. What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Runtime • Compile-time • Macros • Domain Specific Language support • Ecosystem • Community/Team • Ability to change the language at runtime • Ability to change the language during the compilation process • Macros provide a homogeneous form for writing AST transformations Awesome
  • 126. Part 2: What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support  Command chains • Cranes and tortoises revisited • Ecosystem • Community/Team
  • 127. Command Chains • Ability to chain method calls without parentheses and dots Awesome
  • 128. Command Chains • Ability to chain method calls without parentheses and dots move forward at 3.km/h
  • 129. Command Chains • Ability to chain method calls without parentheses and dots • Equivalent to: move forward at 3.km/h move(forward).at(3.getKm().div(h))
  • 130. Command chains in DSLs Number.metaClass.getShares = { delegate } Number.metaClass.getDollars = { delegate } String GOOG = 'Google' def sell(int nShares) { [of: { String ticker -> [at: { int price -> println "Sold $nShares $ticker at $$price" }] }] } sell 100.shares of GOOG at 1000.dollars
  • 131. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please show the square_root of 100 // ==> 10.0
  • 132. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please(show).the(square_root).of(100) // ==> 10.0
  • 133. Command chains in DSLs show = { println it } square_root = { Math.sqrt(it) } def please(action) { [the: { what -> [of: { n -> action(what(n)) }] }] } please(show).the(square_root).of(100) // ==> 10.0 … and again in another language …
  • 134. Command chains in DSLs // Japanese DSL Object.metaClass.を = Object.metaClass.の = { clos -> clos(delegate) } まず = { it } 表示する = { println it } 平方根 = { Math.sqrt(it) } まず 100 の 平方根 を 表示する // First, show the square root of 100 // => 10.0 // source: http://d.hatena.ne.jp/uehaj/20100919/1284906117 // http://groovyconsole.appspot.com/edit/241001
  • 135. Part 3: What makes Groovy Awesome? • Java integration • Scripting support • Multiparadigm • Gradual typing • Metaprogramming • Domain Specific Language support • Command chains  Cranes and tortoises revisited • Ecosystem • Community/Team
  • 136. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs How many of each animal?
  • 137. Recall: Constraint programming example @Grab('org.choco-solver:choco-solver:4.0.0') import org.chocosolver.solver.Model def m = new Model() def totalAnimals = 7 def totalLegs = 20 def numCranes = m.intVar('Cranes', 0, totalAnimals, true) def numTortoises = m.intVar('Tortoises', 0, totalAnimals, true) def numCraneLegs = m.intScaleView(numCranes, 2) def numTortoiseLegs = m.intScaleView(numTortoises, 4) m.arithm(numCranes, '+', numTortoises, '=', totalAnimals).post() m.arithm(numCraneLegs, '+', numTortoiseLegs, '=', totalLegs).post() if (m.solver.solve()) println "$numCranesn$numTortoises" else println "No Solutions" Cranes = 4 Tortoises = 3 ChocoCraneTortoise.groovy
  • 139. Logic programming example cranes have 2 legs tortoises have 4 legs there are 7 animals there are 20 legs display solution Cranes 4 Tortoises 3 dslUntyped/ChocoCraneTortoiseDSL.groovy 50 lines to define the DSL
  • 140. Logic programming example cranes have 2 legs tortoises have 4 legs millipedes have 1000 legs there are 8 animals there are 1020 legs display solution Cranes 4 Tortoises 3 Millipedes 1 dslUntyped/ChocoCraneTortoiseDSL.groovy 50 lines to define the DSL
  • 141. Logic programming example Crane(2), Tortoise(4), Beetle(6), Centipede(100), Millipede(1000) Solution: Tortoise = 3, Beetle = 23 Solution: Crane = 1, Tortoise = 1, Beetle = 24 Solution: Crane = 25, Centipede = 1 dslTyped/ChocoCraneTortoiseDSL.groovy 80 lines to define the DSL @TypeChecked def main() { animals seen include Crane, Tortoise, Beetle, Centipede leg count is 150 head count is 26 display solution }
  • 142. @TypeChecked def main() { animals seen include Crane, Tortoise, Beetle, Centipede leg count is 150 head count is 26 display solution } Logic programming example dslTyped/ChocoCraneTortoiseDSL.groovy 80 lines to define the DSL
  • 143. DSL Type Provider unresolvedVariable { var -> if (!cachedAnimalNames) { def accessKey = '72ddf45a-c751-44c7-9bca-8db3b4513347' // for illustrative purposes, just download xml for a few animals def uid = 'ELEMENT_GLOBAL.2.104550,ELEMENT_GLOBAL.2.105196,ELEMENT_GLOBAL.2.120227' def base = "https://services.natureserve.org/idd/rest/ns/v1.1/globalSpecies" def url = "$base/comprehensive?uid=$uid&NSAccessKeyId=$accessKey" def root = new XmlParser().parse(url) def names = root.globalSpecies.classification.names cachedAnimalNames = names.natureServePrimaryGlobalCommonName*.text()*.replaceAll(' ','') } if (var.name in cachedAnimalNames) { storeType(var, STRING_TYPE) handled = true enclosingClassNode.addField(var.name, 0, STRING_TYPE, new ConstantExpression(var.name)) } }
  • 144. DSL Type Provider @TypeChecked(extensions='NatureServeAnimalProvider.groovy') def main() { animals seen include SandhillCrane, GopherTortoise, ChihuahuanMillipede leg count is 1020 head count is 8 display solution } Custom checker provider/ChocoCraneTortoiseProvider.groovy 80 lines to define the DSL 25 lines to define the provider
  • 148. Groovy's Awesome Team +100's of others Direct downloads: 2013: approx. 3 million 2014: 4+ million 2015: 12+ million now: 2+ million/month
  • 149. Groovy's Awesome Team +100's of others just like YOU!
  • 150.
  • 151. http://www.manning.com/koenig2 Groovy in Action 2nd edition Manning promo code: ctwg3sum (39% off all Manning books) 152