Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
Chapter 4

[ 69 ]

Closures can look deceptively similar to method calls in their usage. In the next code
snippet, we will create a variable called greet and assign a closure to it. This closure
is just a snippet of code enclosed in braces, which prints a greeting. Regular methods
have their own local scope and can only access variables defined within that scope
or member fields in the containing class. Closures, on the other hand, can reference
variables from outside their own scope, as illustrated in the following code.
Closures can be invoked by applying the method call syntax to the variable
containing the closure:


given: "a variable in scope"
def greeting = "Hello"
and: "a closure that can access the variable"
def greet = { println "$greeting, World!"}
when: "we invoke the closure with variable different"
greet()
greeting = "Goodbye"
greet()
then: "the output is as expected"
"""Hello, World!
Goodbye, World!""" == output()

Closures can also accept parameters, but they have their own particular syntax for
doing so. The next closure accepts a parameter, greeting. Multiple parameters can
be defined by separating them with commas. Parameters can also have an optional
type annotation:


given: "a closure which takes a single parameter"
def greet = { greeting -> println "$greeting, World!"}
when: "we call closure with a single parameter"
greet("Hello")
then: "that parameter was what was passed"
"Hello, World!" == output()

given: "a closure which takes a several parameters"
def greet = { String greeting, name ->
println "$greeting, $name!"
}
when: "we call closure with two parameters"
greet("Goodbye", "Fred")
then: "that parameter was what was passed"
"Goodbye, Fred!" == output()
Free download pdf