Groovy: an agile dynamic language for the Java Platform
Closure: Groovy's way of providing transparent callback, used for two particular areas: collection iteration and resources handling.
{ [closureArguments->] statements }
(1..10).each{counter -> log += counter}
// method inject(object, closure)
[1, 2, 3].inject(0) {count, item -> count + item}
// multiple parameter
map = ['a':1, 'b':2]
map.each{ key, value -> map[key] = value * 2}
// call closure
def adder = {x, y -> return x + y}
assert adder(4, 3) == 7
assert adder.call{2, 6} == 8
// curried closure
def adder = {x, y -> return x + y}
def addone = adder.curry(1)
assert addone(5) == 6
Think of the arrow as an indication that parameters are passed from the method on the left into the closure body on the right.
The real power for currying comes when the closure's parameters are themselves closures. Using composition, two or more simple closures can be combined to produce a more elaborate one.
GroovyBeans: when no visibility modifier attached to field declaration, a
property is generated. i.e., a private field and two public accessor methods (overridable). (Note that property!=field). When
final keyword is used, the property will only be readable, not setter method created.
class MyBean implements Serializable {
String myprop; // default visibility
}
Multimethods: Groovy's mechanics of method lookup take the dynamic type of method arguments into account, whereas Java relies on the static type. (Note: The dynamic binding of Java (Polymorphism) is for caller object, not method argument). e.g., Object's default equals method can be overridden as:
class Equalizer {
boolean equals(Equalizer e) {
return true
}
}
GPaths spread-dot operator: list*.member where
*. is called spread-dot operator and member can be a field access, a property access, or a method call.
list*.member <==> list.collect{ item -> item?.member }
list.property <==> list.collect{ item -> item?.property } // abbre of special case for property