groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Winnebeck, Jason" <Jason.Winneb...@windstream.com>
Subject Closure capturing reference versus snapshot
Date Tue, 31 Mar 2015 13:15:03 GMT
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.

Mime
View raw message