Why can't I change the values โ€‹โ€‹of an array in a method?

In the code snippet below, the array deckmust be equal [6,9,5,6,5,1,2], since Ruby passes arrays by reference. After calling the method, the deck values โ€‹โ€‹do not change. Why is this?

def count_cut!(deck)
  s1, s2 = deck[0, deck.last], deck[deck.last..-2]
  deck = s2 + s1 + [deck.last]
end

deck = [5, 1, 6, 9, 5, 6, 2]
count_cut!(deck)
p deck

I am using Ruby 1.9.2-p180.

+3
source share
4 answers

The destination deckdoes not mutate the array that was passed. It is considered as a local variable in the domain of function definition. You can call deck.replaceif you really want to change it.

+8
source

Do it in the Ruby way: instead of modifying the original array, return the modified array:

def count_cut(deck)
  s1, s2 = deck[0, deck.last], deck[deck.last..-2]
  s2 + s1 + [deck.last]
end

Then the caller assigns the return value deck:

deck = [5, 1, 6, 9, 5, 6, 2]
deck = count_cut(deck)
p deck

Deck, :

class Deck

  def initialize(cards)
    @cards = cards
  end

  def count_cut!
    s1, s2 = @cards[0, @cards.last], @cards[@cards.last..-2]
    @cards = s2 + s1 + [@cards.last]
  end

end

deck = Deck.new [5, 1, 6, 9, 5, 6, 2]
deck.count_cut!
p deck
+5

. + Array . .unshift .

deck = [1,2,3,4,5]
p deck.object_id #some_number
deck = [6] + deck
p deck.object_id #another_number
deck.unshift([7])
p deck.object_id #unchanged 
+2

You do not change the array that refers to the variable deck, you simply assign the new array to a local variable deck:

deck = s2 + s1 + [deck.last]

The above array creates a new array whose contents s2 + s1 + [deck.last], this new array is then assigned to a local variable deck. The array referenced deckremains unchanged. If you want to change the array, you will need something like this:

deck_last = deck.last
deck.clear
deck.push(*s2)
deck.push(*s1)
deck.push(deck_last)

or you lose the connection between the local variable deckand the non-local array that it refers to.

+1
source

All Articles