Groovy - 闭包和绑定,为什么这段代码不起作用?
我认为这是一个新手问题,但为什么最后一个断言失败了? 我认为闭包绑定了它上面的值,因此从闭包中更改它将会更改闭包外部的值。
def value = 5
def foo(n){
return {
++n
}
}
def test = foo(value)
assert test() == 6
assert test() == 7
assert value == 7
感谢您的帮助。
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 from 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这确实看起来很奇怪,但我认为这是正确的。所有对象事件整数均通过引用传递。调用 foo(value) 将值传递给函数。变量“n”是对与“值”引用相同的对象的引用。本质上你有两个指向同一个对象的指针。当您增加“n”时,您仅增加该变量。
由于 Integer 类是不可变的 ++n 实际上正在做类似的事情:
这是将递增的值分配给变量 n。顶部声明的变量“value”仍然指向原始对象 5。
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:
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.
请记住,Integer(
value
的运行时类型)是不可变的。因此,虽然n
和value
最初引用同一个对象,但当您执行++n
时,它会创建一个新的Integer
>。value
引用不会更新以引用此新对象,因此当执行完成时,它仍然引用初始对象 (5)。Remember that Integer (the runtime type of
value
) is immutable. So althoughn
andvalue
initially refer to the same object, when you execute++n
it creates a newInteger
. Thevalue
reference is not updated to refer to this new object, so when execution completes it is still referring to the initial object (5).您正在为名称
n
分配一个新值,该值与名称value
不同。您可以通过将value
设为可变对象来获得您想要的行为。然后您可以更改它,而不是创建和分配新对象。这是一个将值包装在列表中的简单示例:
You are assigning a new value to the name
n
, which is different than the namevalue
. You can get the behaviour you want by makingvalue
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: