Creative Commons Licence This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License

Clever Things People Do In Groovy So You Have To Know About Them

Andy Balaam
artificialworlds.net/blog

Contents

Motivation

interfaithramadan.com/2012/08/the-11-basic-facial-reactions-to-seeing.html

Optional semicolons

a = 3 + 1 println(a)

Optional semicolons

a = 3 + 1 println(a) 4

Optional semicolons

b = 3 + 1 println(b)

Optional semicolons

b = 3 + 1 println(b) 3

Optional semicolons

c = 3\ + 1 println(c)

Optional semicolons

c = 3\ + 1 println(c) 4

Optional semicolons

d = (3 + 1) println(d)

Optional semicolons

d = (3 + 1) println(d) 4

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(1, 2)

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(1, 2) 1 2

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs 3, 4

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs 3, 4 3 4

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) 6

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) 6 Caught: groovy.lang.MissingMethodException: No signature of method: tmp.printArgs() is applicable for argument types: (java.lang.Integer) values: [5]

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) {}

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) {} 5 tmp$_run_closure1@1ffe63b9

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) {println("6")}

Optional parentheses and dots

def printArgs(a, b) { println(a) println(b) } printArgs(5) {println("6")} 5 tmp$_run_closure1@1ffe63b9

Optional square brackets

x = [a:3, b:4] println(x)

Optional square brackets

x = [a:3, b:4] println(x) [a:3, b:4]

Optional square brackets

x = a:3, b:4 println(x)

Optional square brackets

x = a:3, b:4 println(x) org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: /home-andrebal-writing/groovy/videos-groovy-clever-things/groovy-maze/tmp.groovy: 1: expecting EOF, found ':' @ line 1, column 6. x = a:3, b:4 ^ 1 error

Optional square brackets

println(a:3, b:4)

Optional square brackets

println(a:3, b:4) [a:3, b:4]

Optional square brackets

println a:3, b:4

Optional square brackets

println a:3, b:4 [a:3, b:4]

Extension methods

4.times {println("Andy is cool")}

Extension methods

4.times {println("Andy is cool")} Andy is cool Andy is cool Andy is cool Andy is cool

Extension methods

def letters = new TreeMap([ "a": 2, "b": 3, "c": 4, "z": 1, ]) letters.each {println(it)}

Extension methods

def letters = new TreeMap([ "a": 2, "b": 3, "c": 4, "z": 1, ]) letters.each {println(it)} a=2 b=3 c=4 z=1

Extension methods

def letters = new TreeMap(["a":2, "b":3, "c":4, "z":1]) Map.metaClass.eachInValueOrder = { entries = new ArrayList(entrySet()) entries.sort({e1, e2 -> e1.getValue() - e2.getValue()}) entries.each(it) } letters.eachInValueOrder {println(it)}

Extension methods

def letters = new TreeMap(["a":2, "b":3, "c":4, "z":1]) Map.metaClass.eachInValueOrder = { entries = new ArrayList(entrySet()) entries.sort({e1, e2 -> e1.getValue() - e2.getValue()}) entries.each(it) } letters.eachInValueOrder {println(it)} z=1 a=2 b=3 c=4

Operator overloading

class PipeConcat { String c def plus(y) { "$c|$y.c" } } def x = new PipeConcat(c:"foo") def y = new PipeConcat(c:"bar") println(x + y)

Operator overloading

class PipeConcat { String c def plus(y) { "$c|$y.c" } } def x = new PipeConcat(c:"foo") def y = new PipeConcat(c:"bar") println(x + y) foo|bar

Example

Example

_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_ _%_*_._._._._._._%_._._._._._._*_%_ _%_._%_%_._%_._%_%_%_._%_._%_%_._%_ _%_._._._._%_._._._._._%_._._._._._ _%_%_%_%_._%_%_%_._%_%_%_._%_%_%_%_ _._._._._._%_._|_._|_._%_._._._._._ _%_%_%_%_._%_%_%_._%_%_%_._%_%_%_%_ _%_._._._._%_._._._._._%_._._._._._ _%_._%_%_._%_._%_%_%_._%_._%_%_._%_ _%_*_+_._._._._._%_._._._._._._*_%_ _%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_%_

Example

class MazeUnderScore { def mod(MazeUnderScore other) { this } def or(MazeUnderScore other) { this } def plus(MazeUnderScore other) { this } def multiply(MazeUnderScore other) { this } def get_() { new MazeUnderScore() } } def _ = new MazeUnderScore()

Example

// ... logic = new Logic() // ... at start then ghosts.mode becomes normal when ghost hits player then player dies when player hits pill then ghosts.mode becomes scared and pill becomes deleted rules done logic.rules.each {println(it)}

Example

logic = new Logic() at start then ghosts.mode becomes normal when ghost hits player then player dies when player hits pill then ghosts.mode becomes scared and pill becomes deleted rules done logic.rules.each {println(it)} on(start, setValue(ghosts.mode, normal)) on(ghost.hits(player), dies(player, null)) on(player.hits(pill), setValue(ghosts.mode, scared)) on(player.hits(pill), setValue(pill, deleted))

Example

class Logic { def rules = [] // ... def at(time) { changeEvent(time) } // ... def then(object) { changeObject(object) } }

Trailing closures

def doItTwice(fn) { fn() fn() } doItTwice({println("d")})

Trailing closures

def doItTwice(fn) { fn() fn() } doItTwice({println("d")}) d d

Trailing closures

def doItTwice(fn) { fn() fn() } doItTwice { println("e") }

Trailing closures

def doItTwice(fn) { fn() fn() } doItTwice { println("e") } e e

build.gradle

dependencies { compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.22' }

build.gradle

// Implicit static imports of dependencies and compile dependencies({ compile(["group": 'org.slf4j', "name": 'slf4j-api', "version": '1.7.22']); });

Jenkinsfile

pipeline { stages { stage('Build') { steps { echo "Building all the projects" dir('sms/whist') { catchError { sh "make"

Jenkinsfile

// Implicit static imports ... pipeline({ stages({ stage('Build', { steps( { echo("Building all the projects") dir('sms/whist', { catchError( { sh("make")

Gotcha: String interpolation

dontRunMe = {-> println("dontRunMe!") "you ran me, didn't you?" } println(dontRunMe) "dontRunMe=$dontRunMe"

Gotcha: String interpolation

dontRunMe = {-> println("dontRunMe!") "you ran me, didn't you?" } println(dontRunMe) "dontRunMe=$dontRunMe" dontrunme1$_run_closure1@4690b489

Gotcha: String interpolation

dontRunMe = {-> println("dontRunMe!") "you ran me, didn't you?" } println(dontRunMe) "dontRunMe=$dontRunMe".toUpperCase()

Gotcha: String interpolation

dontRunMe = {-> println("dontRunMe!") "you ran me, didn't you?" } println(dontRunMe) "dontRunMe=$dontRunMe".toUpperCase() dontrunme1$_run_closure1@4690b489 dontRunMe!

Fun

yoable = [yo:null] def coolPrint(message) { println(message) yoable } coolPrint("s'up?")

Fun

yoable = [yo:null] def coolPrint(message) { println(message) yoable } coolPrint("s'up?") s'up?

Fun

yoable = [yo:null] def coolPrint(message) { println(message) yoable } coolPrint("s'up?") yo

Fun

yoable = [yo:null] def coolPrint(message) { println(message) yoable } coolPrint("s'up?") yo s'up?

Questions?