可变值在ruby中无意中重新分配

时间:2012-06-14 23:29:19

标签: ruby arrays multidimensional-array iteration

我还在学习红宝石的基础知识,所以我想我会尝试制作一个乘法表

x = (0..7).to_a
y = []
x.each { y << x }

y现在是一个8x8数组,每行相等。这些只是我不想要的占位符值,所以我尝试迭代数组索引来更改值。

x.each { |i| y[i][i] = i * i }

此时,y成为包含8列[0, 1, 4, 9, 16, ...]的数组。我明白为什么我只接收平方值,但是我不明白为什么y[1][3]会被改变,例如,当我只期望[1][1],{等指数的值时{1}}要改变。

此外,[2][2]的值也被重新分配给x,即使我从未故意重新分配其价值。通过上面的代码部分,它的值会自动重新分配,我无法理解为什么。

我总是可以自己查找另一种制作这样一个表的方法,但是我想了解[0, 1, 4, 9, 16, ...]发生了什么导致它改变它的值以及为什么迭代遍历索引的行为不符合预期。当我可以理解为什么我更简单的尝试产生无效输出时,我将继续在2D数组的每个索引上更正确地迭代。我想自己弄清楚这个相当基本的任务,但我现在遇到了障碍。

1 个答案:

答案 0 :(得分:5)

您在y中添加了8个对完全相同的对象 x的引用。因此,当您更改y[1][1]时,这与x[1]相同,这与y[2][1]y[3][1]相同,依此类推。

x的值未重新分配。相反,x是一个8元素的数组;此对象是y的元素八倍,并且是x的值; each的每次迭代都在修改该数组的内容。

如果你不习惯,这是非常违反直觉的。也许以下令人毛骨悚然的类比将有所帮助。假设你刚刚建立了一个秘密社团,目前你是唯一的成员。 (这是一个非常秘密社团。)特别是:你是社会的主席,其秘书和财务主管。你也有工作;比方说,你是微软的首席执行官。

现在,一个敌对的秘密社团的成员来到并打破了你的秘密社团主席的左脚趾。 (显然它不够秘密。)另一个来了,打破了局长的右膝盖骨。另一个人砸碎了财务主管的牙齿。现在,事实证明,微软的首席执行官已经遭受了所有这些侮辱。怎么可能?没有人告诉任何人打破微软首席执行官的膝盖!

当然这并不困难:同一个人可以填补所有这些角色;如果你要求红树林 - 喉咙摇摆乐协会主席,就好像你要求其秘书一样,或者你是否要求微软首席执行官,你就会得到完全相同的人。

在Ruby(以及许多其他类似的语言)中,变量与其值之间的关系,或数组中的位置以及所持有的东西,更像是官方帖子与其持有者之间的关系,例如,像一个盒子和它的内容之间的关系。完全相同的事情可能是许多变量的价值,就像完全相同的人可以是总统兼秘书兼财务主管和大笨蛋一样。