On Nov 12, 2013, at 7:09 PM, gvim [email protected] wrote:
return data
end
doit(in)
However, Ruby passes arguments by reference so it seems the variable ‘data’ is
always accessing and changing the file-global variable ‘in’. Is there a more
Perl-like, way of lexicalising the scope of variables passed as arguments to
functions?
gvim
The thing Ive come to in my own understanding is that since everything
is an object in Ruby, that means every variable is actually a pointer to
an object in Ruby as well.
So when you pass in to the doit method, you are passing the reference
into the local method variable data. Initially, data and in are pointing
to the same object. But then you have to be aware of what things you are
doing on the data variable. If its things with modify the same object
originally point to by in, then the object in points to is being
changed. Thus it looks like in is changed.
Doing other things can create new objects in ruby, though, so doing
something to data that ends up creating a new object also ends up
making in look unchanged when doit exits, which is so.
So lets try this.
def doit2(data)
data.shuffle
end
According to the docs, shuffle creates a new array. So:
$ pry
[1] pry(main)> start_data = [1,2,3,4,5].freeze
=> [1, 2, 3, 4, 5]
[2] pry(main)> a_ary = start_data
=> [1, 2, 3, 4, 5]
[3] pry(main)> def doit(data)
[3] pry(main)* data.shuffle
[3] pry(main)* end
=> nil
[4] pry(main)> doit(a_ary)
=> [2, 4, 5, 3, 1]
[5] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[6] pry(main)> a_ary.object_id
=> 70307654300780
[7] pry(main)> doit(a_ary).object_id
=> 70307649978420
[8] pry(main)> doit(a_ary).object_id
=> 70307650161900
So you can see that .shuffle is creating a new object each time.
But remember we froze the source data up there? a_ary is also pointing
to the frozen array, so when you change doit to something like this:
[9] pry(main)> def doit(data)
[9] pry(main)* data.shift
[9] pry(main)* end
=> nil
[10] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[11] pry(main)> a_ary.object_id
=> 70307654300780
[12] pry(main)> b_ary = doit(a_ary)
RuntimeError: can’t modify frozen Array
from (pry):12:in `shift
It fails because we tried to change a frozen object.
Now if we do this:
[13] pry(main)> b_ary = doit(a_ary.dup)
=> 1
[14] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[15] pry(main)>
doit is working on a new object that isnt frozen.