Groovy

  • Fewer imports necessary
  • Groovy Truth → if(0) println(“pass”), if(””) println (“Not pass”), if(object) println (“Pass if object !=null)
  • Public is the default scope, there are only three ones (public, protected, private)
  • Checked exceptions don't have to be caught
  • ?. → access the method only if the object is not null, example person?.name
  • ?: → Elvis-Operator: String name = name.getName() ?: “Unknown” → shortcut for String name = (person.getName() != null) ? person.getName() : “Unknown”
  • *. List names = people*.getName() where people a list of objects having all the method getName()
  • i1 ⇔ i2 (return -1 if i1 < i2, 0 if i1 == i2, 1 if i1 > i2)
  • == is like equals() (except if the left side implements Comparable, then == uses the compareTo()-method) and null-safe
  • is() instanceof
  • as → 5342 as String, or 1234.compareTo(“234” as int), “123” as List, list as Array, list as Set

Running Groovy

  • groovysh → Groovysh
  • groovyConsole → Swing-GUI
  • groovyc → Groovy Compiler
  • Run groovy-class from java → java -cp $GROOVY_HOME/embeddable/groovy-all-1.0.jar:classes Fibonacci

Maps and Lists

  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
  
  

Closures

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)


OO

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'
}

RegEx

  assert "Speaking plain English" =~ /plain/ (enthält)
   assert !("Speaking plain English" ==~ /plain/ (besteht aus)

Closures

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}

Duck typing

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”()

The Groovy JDK

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"}

Gorm

Changes in Version 1.1

Constraints

A list of possible constraints can be found here:
http://www.grails.org/Validation+Reference

GSP

GSP Tag Reference: http://www.grails.org/GSP+Tag+Reference

There are a number of predefined variables usable in GSP's:

  • application - The javax.servlet.ServletContext instance
  • applicationContext The Spring ApplicationContext instance
  • flash - The flash object. A temporary storage map that stores objects within the session for the next request and the next request only, automatically clearing our the objects held there after the next request completes. This pattern allows you to use HTTP redirects (which is useful for redirect after post and retain values that can retrieved from the flash object).
  • grailsApplication - The GrailsApplication instance
  • out - The response writer for writing to the output stream
  • params - The params object for retrieving request parameters
  • request - The HttpServletRequest instance
  • response - The HttpServletResponse instance
  • session - The HttpSession instance
  • webRequest - The GrailsWebRequest instance
 
wettstein/groovy_grails.txt · Last modified: 2011-01-10 10:38 by frank.wettstein
 
Recent changes RSS feed Creative Commons License Powered by GNU/Linux Powered by Gentoo Powered by Apache Powered by XCache Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki