Skip to content

Closures

Philip Ford edited this page Aug 26, 2017 · 30 revisions

Summary

Groovy closures are true closures, with access to the variables in the context in which they are defined. They are:

  • Contained in braces

  • They are functions.

  • But they are also instances of the Closure class.

  • Used in callbacks

  • The default parameter (if you do not provide parameters) is it.

    [1,2,3].each {
       println it
    }

They can be used a lot like lambdas, passed as parameters to another function. (In other words, they are first-class objects.) But the Groovy documentation insists that they should not be thought of as lambdas.

Syntax

{ <type> param1, <type> param2 ... ->
   //Body
}
  • Again, parameters are optional.
  • If no parameters are listed, the default parameter is it.
  • Parameters, if present, are listed (comma-separated) immediately after the first brace, on the first line of the closure, and followed by a arrow.
  • The code body begins on the next line.
  • The output of the last line is the return value, with or without the return statement.

Closures vs. Lambdas

Closures are instances of the Closure class, making them very different from Java 8 lambdas.

Invoking Closures

Closures can be invoked like any other function:

closureName(<params...>)

Alternatively, closures can be invoked with the call method of the Closure class:

def c = { 123 }          // returns 123
assert c() == 123        // true
assert c.call()  == 123  // true

Closures as Parameters

For a function/closure to take a Closure as a parameter, that parameter must be declared as the Closure datatype.1

Example

private defaultResponseHandler = { resp, reader ->
   assert resp.status == 200
   println "My response handler got response: ${resp.statusLine}"
   println "Response length: ${resp.headers.'Content-Length'}"
   System.out << reader // print response reader
}

void fetchContent(String path, Closure c = defaultResponseHandler){
    connect path, TEXT, c
}

In this case, from my HttpClient, I make the Closure parameter optional by giving it a default value. In either case, the closure works as a callback.

References

Notes

  1. Actually "must be declared" may be too strong. Perhaps def would work.

Clone this wiki locally