Closures in Groovy

Groovy supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

def intSeq() {
    def i = 0
    return { -> 
        i++
        return i
    }
}

def main() {
    // We call intSeq, assigning the result (a closure)
    // to nextInt. This closure captures its
    // own i value, which will be updated each time
    // we call nextInt.
    def nextInt = intSeq()

    // See the effect of the closure by calling nextInt
    // a few times.
    println(nextInt())
    println(nextInt())
    println(nextInt())

    // To confirm that the state is unique to that
    // particular closure, create and test a new one.
    def newInts = intSeq()
    println(newInts())
}

main()

In this Groovy example, we define a function intSeq() that returns a closure. The closure closes over the variable i to form a closure.

The main() function demonstrates how to use this closure:

  1. We call intSeq(), assigning the result (a closure) to nextInt. This closure captures its own i value, which will be updated each time we call nextInt.

  2. We then call nextInt() multiple times to see the effect of the closure. Each call increments and returns the captured i value.

  3. To confirm that the state is unique to that particular closure, we create a new closure newInts and call it once.

To run this Groovy script, save it to a file (e.g., closures.groovy) and execute it using the Groovy command:

$ groovy closures.groovy
1
2
3
1

This output demonstrates that the first closure (nextInt) maintains its own state, incrementing from 1 to 3, while the second closure (newInts) starts fresh at 1.

Closures are a powerful feature in Groovy, allowing you to create functions with persistent local state. They are commonly used in various scenarios, including callbacks, iterators, and event handlers.