0

如果在 IRB 控制台中运行以下代码:

arr = [[], 1]
arr[0]<<arr

结果是[[[...], 1]]

此后arr[0], arr[0][0],arr[0][0][0]等产生相同的输出。

这是有道理的,因为我不能显示任意数量的嵌套,对吧?

但是,arr[0][1]产生 nil (而不是1)什么?但arr[0][0][1]打印1

arr[0][0][0][1] => nil

然后:

arr[0][0][0][0][1] => 1

等等

到底是怎么回事?实际创建的结构是什么?这个结构递归的深度有多深?nil 是从哪里来的?

4

2 回答 2

1

看看里面有什么

arr[0]
# => [[[...], 1]]

arr[0]是一个只有一个元素的数组。所以[1]将超出这个数组并返回 nil。

arr[0][0]
# => [[[...]], 1]

arr[0][0]将进入顶部数组的唯一一个元素,并且该元素包含两个值,因此[1]将找到一个值。

它的行为是因为你做了arr[0] << arr而不是arr[0] = arr
通过这样做arr = [[], 1]; arr[0] << arr,您没有设置arr为,arr[0]而是添加arr为 arr[0] 的元素,它本身就是一个数组。

如果你不这样做

arr = ["whatever", 1]
# => ["whatever", 1]
arr[0] = arr
# => [[...], 1]
arr[0][1]
# => 1
arr[0][0][1]

编辑

回到你的问题,为什么它会变成一个递归数组。您不是将arr' 值传递给arr[0]而是它的引用

arr = ["whatever", 1]
# => ["whatever", 1]
arr.object_id
# => 69999412942060
arr[0] = arr
# => [[...], 1]
arr[0].object_id
# => 69999412942060
arr[0].object_id == arr.object_id
# => true

从那时起,您就拥有Ouroboros,arr并且arr[0]指的是同一个对象。
如果你只想插入它的值,你应该先 deep_copied 它。

arr = ["whatever", 1]
arr_copy = Marshal.load(Marshal.dump(arr)) # copy the value,
                                           # delete the object reference dependence
arr[0] = arr_copy
puts arr.inspect
# [["whatever", 1], 1] # no infinit recurrence.
于 2013-06-19T05:10:47.537 回答
1

Array#size也是必不可少的,以证明为什么有时您会看到nil1作为输出:

arr = [[], 1]
arr[0]<< arr
arr.size # => 2
arr # => [[[...]], 1]

arr[0] # => [[[...], 1]]
arr[0].size # => 1
arr[0][1] # => nil

arr[0][0] # => [[[...]], 1]
arr[0][0].size # => 2
arr[0][0][1] # => 1

arr[0][0][0] # => [[[...], 1]]
arr[0][0][0].size # => 1
arr[0][0][0][1] # => nil

arr[0][0][0][0] # => [[[...]], 1]
arr[0][0][0][0].size # => 2
arr[0][0][0][0][1] # => 1
于 2013-06-19T05:14:38.293 回答