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.

Reply via email to