Techioz Blog

Ruby関数に配列を渡す

概要

さて、Ruby が関数に引数を渡す方法に混乱してしまいました。 Rubyが値渡しであることをドキュメントで読みましたが、私の場合は参照渡しのようです 問題は次のとおりです。

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

Ruby は arr 値を値で渡すため、このメソッドを呼び出しても arr 値を変更するべきではありません。ただし、私の場合、元の配列が変更されます。なぜ? コード:

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"

解決策

それを理解するには、変数とその変数が何を表すかを区別する必要があります。次の例を考えてみましょう。

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

Ruby が引数を参照渡しした場合、受け取った引数を使用してメソッド内でこれを行うと、呼び出し元によってメソッドに公開される変数が新しい場所を指すようになります。

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]

Ruby は引数を値で渡しますが、受け取った値は、呼び出されたものと同じメモリ内の場所への参照です。言い換えれば、クローンや複製ではなく、同じオブジェクトが得られます。

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]

メソッドの引数に副作用を与えないようにしたい場合は、メソッドのクローンを作成できます。