I couldn't find a good description on the details of how closures capture their
context at http://groovy-lang.org/closures.html. I thought that closures always
capture a reference (and not a snapshot as in Java anonymous classes), because
this works to print 2:
def i = 1
def x = { println i }
i = 2
x()
However, I'm having a problem getting a more complicated example to work. In
this case it's a DSL where I capture a bunch of closures and run them multiple
times, and expecting them to have state.
Here is the DSL "script"
def x = {
def y = func()
println "top closure: y is $y"
setClosure {
println "nested closure: y is $y"
}
}
And here is the "framework"
class State {
def y
Closure closure
def func() {y}
void setClosure(Closure c) {
if (closure == null) {
println "First time and I'm saving the closure"
closure = c
}
}
}
def s = new State()
s.y = 1
x.delegate = s
x()
//s.with(x)
s.closure()
s.y = 2
x()
//s.with(x)
s.closure()
I know that the with method clones the closure, which is why I tried setting
delegate manually. In either case the output is the same:
top closure: y is 1
First time and I'm saving the closure
nested closure: y is 1
top closure: y is 2
nested closure: y is 1
I'm expecting the nested closure to output "y is 2" because on the second
execution of the same closure, y gets set to 2. It seems the nested closure is
capturing a snapshot of the local variable y instead of a reference. If I move
the declaration of "y" out of the top closure, or somewhere else such as a
field in a containing class, it works as expected.
Jason Winnebeck
----------------------------------------------------------------------
This email message and any attachments are for the sole use of the intended
recipient(s). Any unauthorized review, use, disclosure or distribution is
prohibited. If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message and any attachments.