2012-04-03 11 views
4

私が使用したい問題の方法がgemであり、ここで調達(行17-42):あなたが見ることができるように、nameがライン19上の第一引数に割り当てられているhttps://github.com/rails/rails/blob/master/railties/lib/rails/generators/actions.rbメソッドが引数を変更するのを防ぐには?

、その後、messagenameに割り当てられています23行目、最後にmessage<<で26行目に変異しています。これは残念なことに、最初の引数として渡されている文字列がメソッド外で変更されていることを意味します。私は防ぐことができますどのように

groups => { foo: ["foo (42)", "bar (42)"], bar: ["foobar (42)"] } 

groups = { foo: %w(foo, bar), bar: %w(foobar) } 

groups.each do |group, gems| 
    gems.each do |name| 
    gem(name, "42") 
    end 
end 

その後、私のハッシュはgemの内部変異に起因する以下のようになります。次のように

は、私は配列のハッシュを持ち、それらを反復処理していますこれらの文字列(およびハッシュとその配列)は変更されていますが、メソッドが破られることはありませんか?

+0

文字列をフリーズすると、その文字列は突然変異しなくなりますが、例外が発生するだけです。 –

答えて

1

あなたはname.dupでそれを呼び出すことができます:

gem(name.dup, "42") 

背景:gem(name)を使用すると、渡すあなたが何ができるか

はそうのように、あなたの文字列のクローンでメソッドを呼び出すですパラメータをメソッドに追加します。呼び出されたメソッド内の変更は、元の変数も変更します。

name.dupを使用すると、オブジェクトのコピーを作成します。このコピーは、呼び出されたメソッド内で変更されますが、元の値は変更されません。


警告:dupは常に動作しません。データによって異なります。 dupディープコピーを作成しません。この例を参照してください:

arr = ['a', 'b'] 
arr.dup.map{|x| x << '1'} 
p arr #["a1", "b1"] 

説明:arrがコピーされる配列ではなく、配列内のコンテンツを。 mapの中には、コピーした配列のデータを変更します。しかし、元の配列とコピーされた配列の要素は同じです。元の配列の内容も変更します。

+0

-1。 Rubyには参照による呼び出しはありません。 Rubyは常に*値による呼び出しです。いいえ。いいえ。例外なく。たとえば、次のようになります。 'def foo(bar)bar = 'reference' end; baz = '値'; foo(baz); "Rubyは#by {baz}"と呼ぶ。 –

+0

@JörgWMittag 'def foo(bar)bar << 'ですが、これらの値は通常は参照' endです。 baz = '値'; foo(baz); Rubyが#{baz}によって呼び出されています。 " – dbenhur

+0

@JörgWMittagRubyが常に値渡しの呼び出しをしている場合、なぜ引数を変更するのですか? –

5

(それはそれはやるべきではない何かだから、バグレポートを提出するよりも、他の)あなたは、その引数を変異からメソッドを防ぐことはできません。

gem(name.dup, "42") 
+1

ありがとう!それは私が遭遇した非常に問題のために議論を変えるのは悪い形であると一般に考えられていますか? –

+4

はい、正確に - そのような振る舞いが想定され、文書化されていない限り、引数はメソッド内で変更されるべきではありません。 –

関連する問題