Ruby は参照渡しですか、それとも値渡しですか? 質問する

Ruby は参照渡しですか、それとも値渡しですか? 質問する
@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@userオブジェクトはメソッドlang_errors内の変数にエラーを追加しますupdate_lanugages。オブジェクトを保存すると、変数@userに最初に保存されたエラーが失われますlang_errors

私がやろうとしていることは、むしろハックのようなものですが (うまく機能していないようです)、変数の値が消えてしまう理由を理解したいと思います。参照渡しは理解しているので、その変数に値が消えずに保持される方法を知りたいです。

ベストアンサー1

他の回答者の方々の回答はすべて正しいのですが、友人からこれについて説明してほしいと頼まれました。要するに、Ruby が変数をどのように処理するかということです。そこで、友人のために私が書いた簡単な図と説明をいくつか共有しようと思いました (長くて、おそらく単純化しすぎていることをお詫びします)。


strQ1:に新しい変数を割り当てると何が起こりますか'foo'?

str = 'foo'
str.object_id # => 2000

ここに画像の説明を入力してください

A: オブジェクト を指す というラベルstrが作成されます'foo'。この Ruby インタープリタの状態では、そのオブジェクトはメモリ位置 にあります2000


Q2: を使用して既存の変数をstr新しいオブジェクトに割り当てるとどうなりますか=?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

ここに画像の説明を入力してください

A: ラベルがstr別のオブジェクトを指すようになりました。


=Q3:に新しい変数を割り当てると何が起こりますかstr?

str2 = str
str2.object_id # => 2002

ここに画像の説明を入力してください

A:と同じオブジェクトstr2を指す という新しいラベルが作成されます。str


Q4: によって参照されるオブジェクトが変更されるとどうなりますstrstr2?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

ここに画像の説明を入力してください

A: 両方のラベルはまだ同じオブジェクトを指していますが、そのオブジェクト自体は変化しています (その内容が別のものに変化しています)。


これは元の質問とどう関係するのでしょうか?

これは基本的に Q3/Q4 で発生することと同じです。メソッドは、渡さstr2れる変数/ラベル ( ) の独自のプライベート コピーを取得します ( )。ラベルが指すstrオブジェクトを変更することはできませんが、両方が参照するオブジェクトの内容を、else に含めるように変更できます。str

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004

おすすめ記事