我有Ruby代码:
def test_111(hash)
n = nil
3.times do |c|
if n
n[c] = c
else
n = hash
end
end
end
a = {}
test_111(a)
p a
打印的原因 {1=>1, 2=>2}
,不是 {}
??
在test_111方法中, hash 和 a 使用相同的内存?
如何在test_111方法中更改 a 值?
我无法理解
答案 0 :(得分:4)
哈希通过引用传递。因此,当您更改方法参数(这是一个哈希)时,您可以更改原始哈希值。
为避免这种情况,您应该克隆哈希值。
test_111(a.dup)
这将创建一个浅拷贝(也就是说,它不会克隆你可能拥有的子哈希)。
浅层副本的一个小例子:
def mutate hash
hash[:new] = 1
hash[:existing][:value] = 2
hash
end
h = {existing: {value: 1}}
mutate h # => {:existing=>{:value=>2}, :new=>1}
# new member added, existing member changed
h # => {:existing=>{:value=>2}, :new=>1}
h = {existing: {value: 1}}
mutate h.dup # => {:existing=>{:value=>2}, :new=>1}
# existing member changed, no new members
h # => {:existing=>{:value=>2}}
答案 1 :(得分:0)
在ruby中,几乎每个对象都通过引用传递。这意味着当你做一些简单的事情
a = b
除非a是其中一种简单类型,否则此作业a
和b
将指向相同的内容。
这意味着如果你改变第二个变量,第一个变量会受到同样的影响:
irb(main):001:0> x = "a string"
=> "a string"
irb(main):002:0> y = x
=> "a string"
irb(main):003:0> x[1,0] = "nother"
=> "nother"
irb(main):004:0> x
=> "another string"
irb(main):005:0> y
=> "another string"
irb(main):006:0>
当然这同样适用于哈希:
irb(main):006:0> a = { :a => 1 }
=> {:a=>1}
irb(main):007:0> b = a
=> {:a=>1}
irb(main):008:0> a[:b] = 2
=> 2
irb(main):009:0> a
=> {:a=>1, :b=>2}
irb(main):010:0> b
=> {:a=>1, :b=>2}
irb(main):011:0>
如果您不希望发生这种情况,请使用.dup
或.clone
:
irb(main):001:0> a = "a string"
=> "a string"
irb(main):002:0> b = a.dup
=> "a string"
irb(main):003:0> a[1,0] = "nother"
=> "nother"
irb(main):004:0> a
=> "another string"
irb(main):005:0> b
=> "a string"
irb(main):006:0>
对于大多数人dup
和clone
具有相同的效果。
因此,如果您编写一个修改其中一个参数的函数,除非您特别希望调用该函数的代码看到这些更改,您应首先复制正在修改的参数:
def test_111(hash)
hash = hash.dup
# etc
end
代码的行为称为副作用 - 对程序状态的更改,而不是函数的核心部分。通常要避免副作用。