将数组传递给Array#each,在内部,它使用引用或值

时间:2011-03-09 22:24:32

标签: ruby pass-by-reference

array1 = [0, 1]

# CASE 1:  
[array1].each do |arr| 
  arr = [3, 4] 
end

=> [0, 1]

# CASE 2:
[array1].each do |arr| 
  arr.delete_if { |ele| ele == 0 }
end

=> [[1]]

我认为ruby总是通过引用传递数组。为什么不在CASE 1中更改数组的值,但在CASE 2中更改了它?感谢。

3 个答案:

答案 0 :(得分:2)

在您的第一种情况下,您所做的就是更改哪个对象arr指向 - 您实际上没有修改过原始对象。这可以通过以下脚本证明:

# Given our test value...
test_array = [1, 2]

# we can verify the values and the object_ids
puts "Value of `test_array`: #{test_array.inspect}"
puts "Object_id of `test_array`: #{test_array.object_id}"

# now, let's put it in a container and run it through a block
@array_container = [test_array]

@array_container.each do |arr|

  # Just to prove that `arr` points at test_array
  puts "Object_id of `arr`: #{arr.object_id}"

  # and that it's the same as the first element in our container
  puts "@container.first.object_id: #{@array_container.first.object_id}"

  # but, when we re-assign our block variable
  arr = [3, 4]

  # we get different values
  puts "Object_id of `arr`: #{arr.object_id}"
  puts "@container.first.object_id: #{@array_container.first.object_id}"
end

哪些输出......

Value of `test_array`: [1, 2]
Object_id of `test_array` : 2150710260

Object_id of `arr`        : 2150710260
@container.first.object_id: 2150710260

Object_id of `arr`        : 2150708040
@container.first.object_id: 2150710260

那么案例2中的情况有何不同?在案例2中,您实际上是在调用自毁方法,该方法将对arr

引用的原始对象进行更改

答案 1 :(得分:0)

我认为你的问题与范围有关。 do-end构造实际上是一个新块,因此当您声明arr = [3, 4]时,您正在该块中实例化一个新的arr = [3, 4]。而在案例2中,您直接修改引用。在案例1中做同样的事情就像是:

[array1].each do |arr| 
  arr.each_index do |i|
    arr[i]+=3
  end 
end

=> [[3,4]]

答案 2 :(得分:0)

.each只是依次调用该块的每个元素(在本例中为[array1])。传递参数只是将其赋值给参数。您的示例可以简化为以下内容:

# CASE 1:  
array1 = [0, 1]
arr = array1
arr = [3, 4]
array1

=> [0, 1]

# CASE 2:
array1 = [0, 1]
arr = array1
arr.delete_if { |ele| ele == 0 }
array1

=> [1]