0

I'm changing local variable params in some_method:

def some_method params
  params.object_id       # => 70163816155080 
  params[:name]  = 'bar'
  params.object_id       # => 70163816155080 Why is this not changing after I changed the value?
end

details  = {name: 'foo'}
details.object_id   # => 70163816155080
some_method details
details             # => {:name=>"bar"}

Why is it changing the original variable details? Does Ruby use pass by reference for hash?

sawa
  • 165,429
  • 45
  • 277
  • 381
Bibek Sharma
  • 3,210
  • 6
  • 42
  • 64
  • 2
    what exactly is the question? the method is changing the name key to `bar` – dax Sep 25 '15 at 08:21
  • 1
    I'm changing local variable `params` on `some_method`. Why is is changing the original variable.Does Ruby pass by reference for hash? – Bibek Sharma Sep 25 '15 at 08:24
  • 1
    .. i think your expecting `ruby` to act like `c` or some language where you need to pass a reference to a method to change the `concrete` object. `ruby` does not work that way. – ptierno Sep 25 '15 at 08:24
  • @ptierno thank you !! can you please describe in more details? – Bibek Sharma Sep 25 '15 at 08:30
  • @BibekSharma not really, as I'm just learning languages with pointers and such myself (go/c). All I know is that ruby treats every object passed to a method as concrete, and in such modifies the ACTUAL object, not a copy of it. Hope this helps a bit. – ptierno Sep 25 '15 at 08:32
  • 2
    possible duplicate of [Is Ruby pass by reference or by value?](http://stackoverflow.com/questions/1872110/is-ruby-pass-by-reference-or-by-value) – ndnenkov Sep 25 '15 at 08:33
  • @ptierno Thank you. It helps to make some sense. – Bibek Sharma Sep 25 '15 at 08:36
  • @BibekSharma read some of the answers. I was wrong in about the my assumptions in a few situations. – ptierno Sep 25 '15 at 08:37

2 Answers2

1

Some incorrect assumptions on your part

I'm changing local variable params in some_method

No, you're not. Well, yes, you are changing some state of params, but the object is not replaced, it stays the same. Hence the persistence of its object_id. If you were to replace the object, then the object_id would change:

def some_method params
  params = { name: 'bar' } # this is a new object with a new object_id
                           # this assignment won't be visible to the outside

Why is this not changing after I changed the value?

There are languages with immutable data structures. There you have to generate a new version of an object if you want to change some data in it. Ruby is not one of those languages. Its data structures are very mutable.

Why is it changing the original variable details

Because these references refer to the same object in memory. See the many links about "pass-by-reference-by-value" posted in answers and comments here.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
0

Ruby pass everything by reference except Integer, Floats and Symbols just for convenience.


UPDATE: It's called immediate values.

immediate values are not pointers: Fixnum, Symbol, true, false, and nil are stored directly in VALUE

You even can't define method for this kind of values:

x = :hello
def x.test; end

Will raise an error


MORE:

For example, Fixnum http://ruby-doc.org/core-2.2.2/Fixnum.html

Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object.

violarium
  • 403
  • 4
  • 12
  • 1
    How did you come up with the idea that integers, strings and symbols are exceptions? – ndnenkov Sep 25 '15 at 08:30
  • 1
    Sorry I was wrong about Strings. In ruby there are no thigs like passing by reference or not, actually. But some types are immutable and they can't be changed inside of it, so new copy is created when you try to change it inside of function. When you add to array new value or change existing, it will be changed outside of method. – violarium Sep 25 '15 at 08:39
  • @violarium, immutability has nothing to with whether something is passed by reference or by value. Something immutable can be passed either way in other languages. – ndnenkov Sep 25 '15 at 08:42
  • 1
    @ptierno, this example doesn't prove anything. You can do the same with strings or any other type and the original `a` won't get changed. This is because the assignment operator (`=`) changes what something points to, it doesn't change the value in the passed reference. – ndnenkov Sep 25 '15 at 08:43
  • @violarium Please see my update Why object_id is not getting changed after I changed the value – Bibek Sharma Sep 25 '15 at 08:56
  • @violarium Can you please add some details. What are you trying to say exactly. "immediate values are not pointers: Fixnum, Symbol, true, false, and nil are stored directly in VALUE"? – Bibek Sharma Sep 25 '15 at 08:58
  • @ndn, In ruby there are not passing by reference or by value like in other languages. Just some values are "immediate" – violarium Sep 25 '15 at 08:59
  • @violarium, immutability has nothing to do with this. By the same logic, you can say that each class that doesn't have anything to be mutated is also an exception. – ndnenkov Sep 25 '15 at 09:00
  • @ndn, I called it in wrong way. Behaviour of passed variables depends on their trait "immediate". http://ruby-doc.org/core-2.2.2/Fixnum.html – violarium Sep 25 '15 at 09:32
  • @BibekSharma, read this: ruby-doc.org/core-2.2.2/Fixnum.html and just keep in mind that everything except this types are "passed by reference" – violarium Sep 25 '15 at 09:41