rubysortingpass-by-referencepass-by-value

Passing array to ruby function


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"

Solution

  • 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.