Ruby #times没有返回我认为应该的东西

时间:2015-09-10 19:47:09

标签: ruby

我期待得到:

array # => [[1, 0], [2, 0]]

如果我运行以下代码:

array = []
position = [0, 0]
2.times do
  position[0] += 1
  array << position
end

我明白了:

array # => [[2, 0], [2, 0]]

有人可以解释一下这里发生了什么吗?

2 个答案:

答案 0 :(得分:4)

position是一个对象。当您致电array << position时,您真正在做的是将position的引用添加到array。这意味着,只要您修改position,所有对它的引用都将反映这些更改。

要获得您期望的结果,您可以在每次传递中复制position数组。这样,后续通行证不会改变你的结果。

array = []
position = [0, 0]

2.times do
  position[0] += 1
  array << position.clone
end

puts array.inspect

答案 1 :(得分:1)

这里的事情是,位置[0]首先等于[0,1]与你的陈述:

position[0] += 1 

这使你看起来像是在挖掘&#39;第一次[0,1],第二次[0,2]。铲运算符的作用是它不像=赋值。这与<<&#39;突变调用者&#39;的概念有关。通过观察它,我发现它更容易理解:

a = "Hello!"
b = a
a << ", my friend"
puts a      # a is now "Hello!, my friend"
puts b      # b is now "Hello!, my friend"

<<运算符不会重新分配a在内存空间中指向的内容。将此与=运算符进行对比,该运算符不会改变调用者:

a = "How about this?"
b = a    # b is now "How about this?"
a = "Not anymore"
puts b   # b is still "How about this?"
puts a   # a is now "Now anymore"

关于使用.clone方法的另一个好答案很重要,因为它可以执行所谓的&#34;浅拷贝&#34;,这意味着对象的实例变量被复制,但是不是他们引用的对象。这就是为什么它适用于这种情况。

希望看到铲子操作员如何工作,并且用它来改变值是改变它的所有它的引用而不仅仅是一个,并使输出在数组中完全相同。如果这没有完全合理,请在评论中告诉我。