I came out with an example of ruby hashes that I cannot quite understand what is happening under the hood:
root = {}
base = root
base[:a] = {}
base = base[:a]
p base
=> {}
p root
=> {:a=>{}}
When I assign base = base[:a]
as I was expecting base
becomes {}
, but why root
doesn't become {}
too?
CodePudding user response:
I just needed a little push to understand, and thanks to @Stefan I think I can answer my own question. Breaking it down we have:
root = {}
base = root
puts root.object_id
=> 47193371579760
puts base.object_id
=> 47193371579760
So both root
and base
became a reference for the same object.
base[:a] = {}
base[:a].object_id
=> 47193372751820
base = base[:a]
puts base.object_id
=> 47193372751820
puts root.object_id
=> 47193371579760
puts root
base[:a]
is a new hash object, and base
assigned to it becomes this object while root
keeps the reference for the old object that was assigned {:a=>{}}
. That's why root
doesn't change at the end.
CodePudding user response:
Array, Symbol and Hash are some reference variables. Similar concept is present in all language. Taking example of javascript, we can relate same with concept of shallow copy & deep copy where hash is replaced by object.
Following is little explanation added for your query.
root = {}
# root = {}
base = root
# both base & root variables point to single location, principle of reference object
base[:a] = {}
# base aka root variable is holding value { a: {} }
base = base[:a]
# base variable is not pointing to root variable location, it is re-assigned with new value which is also hash (reference object)
p base
=> {}
p root
=> {:a=>{}}
base[:b] = 4
=> 4
p base
=> {:b=>4}
p root
=> {:a=>{:b=>4}}
Using object_id
function you can verify address. To make deep copy use clone
function for hash.