Our new Appfire Documentation Space is now live!

Take a look here! If you have any questions please email support@appfire.com

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. Groovy uses closures to specify a code to be executed each time and adds the extra methods ( each, any, every, find, findAll, collect and so forth) to the collection classes to make them readily available. 

See here for more information on Closures.

On this page:

Defining a closure

Simple declaration: The following example shows a simple closure syntax. When there is only one parameter passed into closure, its declaration is optional.

def log = ''
(1..10).each { counter -> log += counter }
log == "12345678910"

//it variable that needs no declaration
def log = ""
(1..10).each { log += it }
log == "12345678910"

Using assignments for declaration: A second way of declaring a closure is to directly assign it to a variable.

//Assigning a closure to a variable
Closure printer = { line -> println line }
printer instanceof Closure //returns true

//Empty closure
def emptyClosure = {}
emptyClosure instanceof Closure //returns true

//Assignment to the return value of a method
def Closure getPrinter() {
return{ line -> println line }
} 
getPrinter() instanceof Closure //returns true

Referring to methods as closures: Declaring a closure is to reuse something that is already declared a method. Groovy lets you reuse the code you already have in methods but as a closure. 

//Method closure assignment statement
def c = reference.&someMethod

//Different implementations are called based on argument types
class MultiMethodSample {
 int mysteryMethod (String value) {
 return value.length()
 }
 int mysteryMethod (List list) {
 return list.size()
 }
 int mysteryMethod (int x, int y) {
 return x+y
 }
}
MultiMethodSample instance = new MultiMethodSample()
Closure multi = instance.&mysteryMethod

multi("Groovy in JMWE") == 14
multi(["a","Red",3.5]) == 3
multi(5,13) == 18

See below for an example that shows all of these ways of creating and using closures

Map map = ['a':1, 'b':2] 
//Closure passed as parameter directly
map.each{key, value -> 
  map[key] = value * 2  
}
map

//Assign a closure object to a variable and call it
doubler = {key, value -> 
  map[key] = value * 2  
}
map.each(doubler)

//Use of reference.&operator
def doubleMethod(entry){ 
 entry.value = entry.value * 2 
}
doubler = this.&doubleMethod 
map.each(doubler)

Calling a closure

A closure, as an anonymous block of code, can be called like any other method.

def code = { 1234 }
code() == 1234
code.call() == 1234

//int as a parameter
def numberIsOdd = { int i -> i%2 !=0 }
numberIsOdd(3) == true
numberIsOdd.call(4) == false

//Same closure with implicit parameter it
def numberIsOdd = { it%2 !=0 }
numberIsOdd(3) == true
numberIsOdd.call(4) == false

Parameters in a Closure

Parameters of closures follow the same principle as parameters of regular methods: an optional type, a name, an optional default value. They are separated with commas. It is possible for a closure to declare variable number of arguments. See the examples below.

//Two Explicit types arguments
def closure = {int a, int b ->
  a + b
}

//Two arguments
def closure = {a,b ->
  a + b
}

//Two arguments with one default
def closure = {int a, b = 5 ->
  a + b
}

//One Explicit type argument
def closure = {String name ->
  it.toUpperCase()
}

//One argument
def closure = {State ->
  it.toUpperCase()
}

//Varargs
def stringConcat = {String... it -> it.join('')}
stringConcat("abc","def","ghi")

def multiConcat = { int n, String... args ->                
    args.join('')*n
}
multiConcat(3,"John"," Carter ")

Using Closures

Some of the useful methods applicable to Closures are listed below. See here for more information.

//finds for the first match
def list = [1,2,30,34,42]
list.find{
	it > 30
}!=null

//finds all the matches
def list = [1,2,30,34,42]
def newList = list.findAll{
	it > 30
} == [34,42]

//Perform an operation on each
Map map = ['a':1, 'b':2] 
map.each{key, value -> 
  map[key] = value * 2  
}
map
  • No labels