开发者

Groovy - Closures and bind, why this code doesn't work?

I think this is a newbie question but why it fails on the last assertion? I was thinking that the closure binds the value on it, so changing it fro开发者_StackOverflowm the closure will change the value outside the closure.

def value = 5

def foo(n){

  return {

    ++n

  }
}

def test = foo(value)

assert test() == 6
assert test() == 7

assert value == 7

Thanks for help.


That does seem to be strange behaviour but I think it is correct. All objects event integegers are passed by reference. The call foo(value) passes value into the function. The variable 'n' is a reference to the same object as 'value' references. Essentially you have two pointers to the same object. When you increment 'n', you are incrementing that variable only.

Since the Integer class is immutable ++n is actually doing something like:

n = n + 1

This is assigning the incremented value to the variable n. The variable 'value' declared at the top is still pointing to the original object 5.


Remember that Integer (the runtime type of value) is immutable. So although n and value initially refer to the same object, when you execute ++n it creates a new Integer. The value reference is not updated to refer to this new object, so when execution completes it is still referring to the initial object (5).


You are assigning a new value to the name n, which is different than the name value. You can get the behaviour you want by making value a mutable object. Then you can change it instead of creating and assigning a new object.

Here's a simple example that wraps the value in a list:

def value = [5]

def foo(n){

    return {

        n[0]++
        n
    }
}

def test = foo(value)

assert test() == [6]
assert test() == [7]

assert value == [7]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜