List myList = ["apple","orange"]
List l = []
Map myMap = [3:"three",4:"four"]
Map m = [:]
Map values = [fred:1, peter:
assert myList[0] == "apple"
assert myList[-1] == "orange"
myList << "lemon"
assert myList[2] == "lemon"
myList[0..1] == ["apple","orange"]
ages = [20,36,42,56]
midage = 21..50
assert ages.grep(midage) == [36,42]
//example which prints a statistics about the number of words in a text
def textCorpus =
"""
Look for the bare necessitites
The simple bare necessitites
Forget about your worries and your strife
I mean the bare necessitites
Old Mother Nature's recipes
That bring the bare necessitites of life
"""
def words = textCorpus.tokenize()
def wordFrequency = [:]
words.each { word ->
wordFrequency[word] = wordFrequency.get(word,0) + 1
}
def wordList = wordFrequency.keySet().toList()
wordList.sort {wordFrequency[it]}
def statistic = "\n"
wordList[-1..-6].each {
word ->
statistic += word.padLeft(12) + ': '
statistic += wordFrequency[word] + "\n"
}
statistic
def benchmark(repeat, Closure worker) {
start = System.currentTimeMillis()
repeat.times{worker(it)}
stop = System.currentTimeMillis()
return stop - start
}
slow = benchmark(1000, {(int) it/2})
fast = benchmark(1000, {it.intdiv(2)})
def test(repeat, Closure worker) {
if(worker.getParameterTypes().size() == 2) {
repeat.times{worker(it)}
}else {
worker(1)
}
}
test(10, {x -> println x}) // result is 1
test(10, {x, y=2 -> println x}) //result is 0 1 2 3 4 5 6 7 8 9
test(10, {x -> println x}) // does not work
Currying (after Haskell Brooks Curry)
-------------------------------------
def adder = {x,y -> return x + y}
def addOne = adder.curry(1)
assert addOne(5) == 6
def multiply = { x, y -> return x * y }
def triple = multiply.curry(3)
def quadruple = multiply.curry(4)
def composition = { f, g, x -> return f(g(x)) }
def twelveTimes = composition.curry(triple, quadruple)
def threeDozen = twelveTimes(3)
The power of closures (functional programming), a log-framework in a handfull of lines
----------------------------------------------
def configurator = {format, filter, line ->
filter(line) ? format(line) : null
}
def appender = {config, append, line ->
def out = config(line)
if (out) append(out)
}
def dateFormatter = {line -> "${new Date()}: $line"}
def debugFilter = {line -> line.contains('debug')}
def consoleAppender = {line -> println line}
def myConf = configurator.curry(dateFormatter,debugFilter)
def myLog = appender.curry(myConf, consoleAppender)
myLog('here is some debug message')
myLog('this will not be printed')
//Double closures
def foo(n) {
return {i -> n + i}
}
def accumulator = foo(5)
accumulator(2)
Accessing with the subscript operator to have a dynamic behavior
Class Counter {
public count = 0
}
def counter = new Counter()
counter.count = 1
assert counter.count == 1
def fieldName = 'count'
counter[fieldName] = 2
assert counter['count'] == 2
Extending the general field-access mechanism
class PretendFieldCounter {
public count = 0
Object get(String name) {
return 'pretend value'
}
void set(String name, Object value) {
count ++
}
}
def pretender = new PretendFieldCounter()
assert pretender.isNoField == 'pretend value'
assert pretender.count == 0
pretender.isNoFieldEither = 'just to increate counter'
assert pretender.count == 1
//Multimethods
def oracle(Object o) {return 'object'}
def oracle(String o) {return 'string'}
Object x = 1
Object y = 'foo'
assert 'object' == oracle(x)
assert 'string' == oracle(y) -> In Java this would be 'object'
//Expando, an object to add dynamically properties and closures
def boxer = new Expando()
assert null == boxer.takeThis
boxer.takeThis = 'ouch!'
assert 'ouch!' == boxer.takeThis
boxer.fightBack = {times -> return takeThis * times}
assert 'ouch!ouch!ouch!' == boxer.fightBack(3)
Spreak operator
def getList(){
return [1,2,3]
}
def sum(a,b,c){
return a + b + c
}
assert 6 == sum(*list)
Add new methods to objects
class StringCalculationCategory {
static def plus(String self, String operand) {
try {
return self.toInteger() + operand.toInteger()
}
catch (NumberFormatException fallback){
return (self << operand).toString()
}
}
}
use (StringCalculationCategory) {
assert 1 == '1' + '0'
assert 2 == '1' + '1'
assert 'x1' == 'x' + '1'
}
assert "Speaking plain English" =~ /plain/ (enthält)
assert !("Speaking plain English" ==~ /plain/ (besteht aus)
Anonymous methods
List fruit = ["Apple", "Orange", "Avocado", "Banana", "Äpfel"]
Closure comparator = {String a, String b -> a.compareTo(b)}
fruit.sort(comparator)
comparator("banana","lemon") < 0
fruit.each {println it}
If I walk like a duck and talks like a duck, it's probably a duck.
Applied to dynamic languages, it means that if an object has a particular property or method signature, then it doesn't matter
what type the object is, you can still call that method or access that property.
def sortPeople(people, property) {
people.sort {p1, p2 -> p1."${property}" <=> p2."${property}" }
}
peopleList.sort() is the same peopleList.”sort”()
Dynamically injected properties and methods.
def glen = personList.find {it.firstName == "Glen"}
def citizens = personList.finaAll {it.city == "Bienne"}
def names = ["Glen","Peter","Alice","Graham","Fiona"]
names.collect {it.size()}
names.sort {it.size()}
names.join(", ")
5.times {println "k"}
A list of possible constraints can be found here:
http://www.grails.org/Validation+Reference
GSP Tag Reference: http://www.grails.org/GSP+Tag+Reference
There are a number of predefined variables usable in GSP's: