Is Ruby pass by reference or by value?

ghz 1years ago ⋅ 6568 views

Question

@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 object adds errors to the lang_errors variable in the update_lanugages method. when I perform a save on the @user object I lose the errors that were initially stored in the lang_errors variable.

Though what I am attempting to do would be more of a hack (which does not seem to be working). I would like to understand why the variable values are washed out. I understand pass by reference so I would like to know how the value can be held in that variable without being washed out.


Answer

In traditional terminology, Ruby is strictly pass-by- value. However, everything in Ruby is an object, so Ruby can appear to behave like pass-by-reference languages.

Ruby breaks the traditional definition of "pass-by-reference" or "pass-by- value" because everything is an object, and when it passes things, it passes references to objects. So really, it Ruby can be classified as a 3rd type of language we might call "pass by object reference." In the strict definition of the computer science term, Ruby is pass-by-value.

Ruby doesn't have any concept of a pure, non-reference value, so you can't pass one to a method. Variables are always references to objects. In order to get an object that won't change out from under you, you need to dup or clone the object you're passed, thus giving an object that nobody else has a reference to. However, even this isn't bulletproof: both of the standard cloning methods do a shallow copy, so the instance variables of the clone still point to the same objects that the originals did. If the objects referenced by the ivars mutate, that will still show up in the copy, since it's referencing the same objects.