Getting Groovy, Part II
Written By: James Williams
- 28 Jul 2006 -
Description: This tutorial introduces you to Groovy, a dynamically-typed scripting language for the Java Virtual Machine. Part II introduces for loops, switch-case, collections, and closures.
Closures
A closure is a reusable block of code with a built-in parameter it. Additional parameters can be specified if needed. Closures can be called on individual objects, are first-class objects themselves, and storeable in arrays and hashs.
We can create custom closures or add our code to pre-defined closure targets.
The general format of the closure body is
{ [optional parameters] -> [code] }
Either of these is valid for defining a closure that prints Hello and the name:
hi = { println "Hi" } hello = { println "Hello" + it } hello = { it -> println "Hello ${it}"} // ${variable} is how to include variables without a //bunch of + signs hello = {println "Hello ${it}"}
Let's redo our n-factorial function from part one to make it groovier:
fact = { if (it == 1) return 1 else return it*fact(it-1) }
We can call closures like functions, or with the call keyword. Any of these are valid:
hi() | hi.call | ||
hello "John" | hello("John") | hello.call "John" | hello.call("John") |
fact 5 | fact(5) | fact.call 5 | fact.call(5) |
The real power of closures is realized when combined with collections and primitive objects.
Instead of using a for or while loop, we could use:
3.times { println "Hi" } 1.upto(5) { println it } 20.downto(15) { println it}
Collections have a bunch of predefined closure targets but for brevity, I'll only talk about my favorites: each and findAll.
each iterates through the collection and executes the closure code on each element. findAll returns a new collection with the elements that satisfy the conditions of the closure.
[1,2,3].each {println it*it} //prints 1 // 4 // 9 ["Jake","John","Cody","Christine"].findAll { it.startsWith("C") } // returns ["Cody", "Christine"]