blob: ca73cebc0180145b1f1b8c363e6cdc83ca9b1165 [file] [log] [blame]
1 Closures
Closures are a powerful way of passing around blocks of executable code.
Think of closures as being like anonymous inner classes in Java that have only a single (anonymous) method.
Closures can be used as an alternative to using iterators; where the container is in full control.
{code:groovy}
[1, 2, 3, 4].each { println(it) }
{code}
Using closures can make the handling of exceptions and the closing of resources much simpler.
For a good example of this see {link:Groovy SQL|sql.html}
1.1 Closures compared to anonymous inner classes
One difference from anonymous inner classes in Java is that Groovy supports ~~true closures~~
where state can be passed into and out of closures. Any local variables in scope
when the closure is created can be used and modified and any variables created within
the closure are visible outside as local variables. No 'final' keyword is required
like with Java and annonymous inner classes.
Consider the following code
{code:groovy}
count = 0
[1, 2, 3, 4].each { count += it; last = it }
println("the sum is ${count} and the last item was ${last}")
{code}
Notice that ~~count~~ goes from the outer scope to the inner scope and back out again after being modified.
The ~~last~~ variable goes from inside scope out.
1.1 Closures are normal objects
Closures are objects that can be passed around and called on demand. So you can do things like this
{code:groovy}
c = { println("Hello ${it}") }
c('James')
c('Bob')
{code}
Each closure is compiled to a new class which is derived from {link:Closure|http://groovy.codehaus.org/apidocs/groovy/lang/Closure.html}.
The above is syntax sugar for.
{code:groovy}
c = { println("Hello ${it}") }
c.call('James')
c.call('Bob')
{code}
1.1 Closure parameters
A closure can take an arbitrary number of parameters like normal Java/Groovy methods.
By default a closure takes a single parameter whose name defaults to being called 'it'. You
can specify any name(s) you wish using a parameter list clause at the start of the closure
declaration.
{code:groovy}
c = { param | println("Hello ${param}") }
c('James')
c('Bob')
{code}
{code:groovy}
c = { a, b, c | println("Hello ${a} ${b} ${c}") }
c('cheese', 234, 'gromit')
{code}
Here is another example of using closures with 2 parameters with the inject() method
which is useful for aggregation.
{code:groovy}
value = [1, 2, 3].inject('counting: ') { str, item | str + item }
assert value == "counting: 123"
value = [1, 2, 3].inject(0) { count, item | count + item }
assert value == 6
{code}
You can see more documentation on closures {link:here|http://wiki.codehaus.org/groovy/BlocksAndClosures}