I just stumbled upon something i don’t quite understand. I know that variables in ruby are references. So that awesome stuff is possible. But when i pass a variable to a method, it behaves strangely:
my_var_a = "nothing happend to me"
my_var_b = "nothing happend to me"
def parse_set(my_var_set)
my_var_set = "my value changed"
end
def parse_sub(my_var_sub)
my_var_sub.sub! /(.*)/, "my value changed"
end
parse_set(my_var_a)
parse_sub(my_var_b)
my_var_a # => "nothing happend to me"
my_var_b # => "my value changed"
Can you explain to me why it works with sub! and = leaves the object unchanged? How can I avoid to use sub! but having the same result?
my_var_aandmy_var_setare different references, but they point at the same object. If you modify the object inmy_var_set, the change shows up inmy_var_a. However, if you repointmy_var_setat a new object, that doesn’t change whatmy_var_apoints at.Edit: clarification…
What Ruby does is called passing references by value. When you say
Ruby saves the string “nothing happend to me” in a memory location (let’s call it 1000), and saves the
my_var_areference in another memory location (let’s say 2000). When your code usesmy_var_a, the interpreter looks at location 2000, see that it points to 1000, then gets the actual string value from 1000.When you call
parse_set(my_var_a), Ruby actually creates a new reference namedmy_var_setand points it to the string thatmy_var_awas pointing at (memory location 1000). However,my_var_setis a copy of themy_var_areference — let’s saymy_var_setwas created at memory location 3000.my_var_aandmy_var_setare 2 completely different references in memory, they just happen to point at the same exact memory location which holds the string value.The statement
my_var_set = "my value changed"inparse_setcreates a new string in memory and pointsmy_var_setat that new memory location. However, this doesn’t change what the originalmy_var_areference points at! Now thatmy_var_setpoints at a different memory location, nothing that you do to that variable will affectmy_var_a.The same reference copy happens for
parse_subas well. But the reason thatparse_subchanges the string is because you’re calling a method directly on themy_var_subreference. When you do this, the interpreter gets the object thatmy_var_subis pointing at and then modifies it. So that change will show up in themy_var_areference, because it still points at the same string.