2

私は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 メソッドでは、hashaは同じメモリを使用しますか?

test_111 メソッドで値を変更するにはどうすればよいですか?

理解できません

4

2 に答える 2

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}}
于 2012-04-22T12:50:17.970 に答える
0

Ruby では、ほぼすべてのオブジェクトが参照によって渡されます。これは、次のような単純なことをするときを意味します

a = b

a が単純型の 1 つであった場合を除き、この代入の後ab同じものを指します。

これは、2 番目の変数を変更すると、最初の変数が同じように影響を受けることを意味します。

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> 

ほとんどの人にとって、同じ効果がありますdupclone

そのため、パラメーターの 1 つを変更する関数を作成する場合は、その関数を呼び出すコードでそれらの変更を確認したい場合を除き、最初に変更するパラメーターを複製する必要があります。

def test_111(hash)
  hash = hash.dup
  # etc
end

コードの動作は副作用と呼ばれ、関数のコア部分ではないプログラムの状態への変更です。一般に、副作用は避けるべきです。

于 2012-04-22T13:06:32.427 に答える