全局数组按功能更改

时间:2015-04-03 23:29:10

标签: ruby

我刚刚开始研究Ruby,我在全局和局部变量范围方面遇到了困难。

处理一个练习题,我发现全局定义的数组正被一个调用它的函数改变。如果我明确地将数组分配给其他东西,则没有任何变化。但是,如果我逐个执行并删除项目,则会将它们从全局数组中删除。

为什么deletepop(我也测试过)方法有这种行为?我从阅读中了解到这应该正在发生,函数内部的“数组”是对arr的值的引用,而不是变量arr。 / p>

(我正在使用Ruby版本2 +)

def change_int x
    x += 2
end

def change_arr array
    array = [4, 5, 6]
end

def pop_arr array
    puts array
    new_array = []

    while array.length > 0
        new_array.push array[0]
        array.delete_at 0
    end

    array
end

x = 5
change_int x
puts x == 5 # true

arr = [1, 2, 3]
change_arr arr
puts arr == [1, 2, 3] # true

old_arr = arr
puts pop_arr arr
puts arr == [1, 2, 3] # false
puts "arr = #{arr}" # arr = []

2 个答案:

答案 0 :(得分:2)

您可以在调用#object_id之前打印pop_arr,在pop_arr内打印这些数组是相同的对象。这意味着参数在Ruby中通过引用传递给函数。

这是代码:

def pop_arr(array)
  puts array.object_id
  # Rest of the fucntion
end

arr = [1, 2, 3]
puts arr.object_id
pop_arr(arr)

所有这些意味着当您在函数内部编辑数组时,它将对传递的对象产生影响。 #delete#delete_at#pop是更改制作它们的数组的操作。

答案 1 :(得分:0)

另请参阅:Ruby - Parameters by reference or by value?Is Ruby pass by reference or by value?

奇怪的是,change_arr不会影响全局数组,但pop_arr会影响你的代码。

以下是发生的事情:ruby将对象的引用作为参数传递给对象。所以像Bartosz说的那样,你可以看到在这些方法的顶部,对象id与你传入的那个匹配;他们引用了同一个对象。

因此,在pop_arr中,当您调用delete_at时,您正在对传入的同一对象进行操作,并且在方法返回后更改仍然存在。

在change_arr中,区别在于您将内部var分配给新对象。传入参数数组时,内部变量引用传入的同一对象。当您实例化一个新的Array对象并为其分配内部数组变量时,内部变量现在引用另一个对象。

def change_arr array
  puts "change id: #{array.object_id}"
  array = [4, 5, 6]
  puts "change id2: #{array.object_id}"
  array
end

这就是为什么在方法结束后更改不会持续存在的原因。如果您想要更改仍然存在,则必须说

array = change_arr(array)

希望有所帮助。