Okay, I got confused by how ruby passes it's arguments to a function. I've read in the documentation that ruby passes by value, but in my case it looks like it's passing by referance Here's the problem:
def buble_sort(arr)
unordered = true
while unordered
unordered = false
for i in (1..arr.size-1)
if(arr[i-1] > arr[i])
arr[i-1], arr[i] = arr[i], arr[i-1]
unordered = true;
end
end
end
arr
end
Calling this method shouldn't modify the arr value, since ruby passes it by value. But in my case, it does modify the original array. Why? Code:
p "#{arr} before sort" # => "[85, -4, 1, 2, 55, 23, 0] before sort"
p buble_sort(arr) # => [-4, 0, 1, 2, 23, 55, 85]
p "#{arr} after sort" # => "[-4, 0, 1, 2, 23, 55, 85] after sort"
To understand that, you have to make a distinction between a variable and what this variable stands for. Consider the following example :
items = [1, 2, 3]
# the variable items points to an array we just instantiated
items = [4, 5, 6]
# items now points to a new array
If ruby passed arguments by reference, doing so within a method with an argument it received would also make the variable exposed to the method by the caller point to a new location
items = [1, 2, 3]
def my_method array
array = [4, 5, 6]
return array
end
my_method(items) # --> [4, 5, 6]
items # --> [1, 2, 3]
# if ruby passed arguments by reference, items would now be [4, 5, 6]
Now ruby passes arguments by value, but the value you received is a reference to the same location in memory as the one the called passed you. In other words, you don't get a clone, a dup, but the same object.
items = [1, 2, 3]
def my_method array
array << 4
return array
end
my_method(items) # --> [1, 2, 3, 4]
items # --> [1, 2, 3, 4]
If you want your method to have no side-effect on its arguments you can clone them.