2011-05-11 64 views
3

在下面的代码片段中,数组deck应该等于[6,9,5,6,5,1,2],因为Ruby通过引用传递数组。方法调用后,卡组的值不会改变。这是为什么?为什么我不能修改方法中数组的值?

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 

我正在使用Ruby 1.9.2-p180。

回答

8

分配给deck不会突变传入的数组。它在函数定义的作用域内被视为一个局部变量。如果你真的想改变它,你可以致电deck.replace

+0

那么为什么甲板是方法范围内的局部变量时,deck.replace会突变甲板?或者仅仅是一种特殊情况? – RaouL 2011-05-11 16:02:41

+2

当你调用'deck = s2 + s1 + [deck.last]'你创建一个新的对象。你可以测试它,如果你把'deck.object_id'放在方法中后,并在'count_cut!(deck)后面' – 2011-05-11 16:14:27

+0

如果你想这样想的话,赋值是一种特殊情况。所有的值都通过Ruby中的引用传递,所以任何修改实例的方法都会修改它。但分配会将该变量更改为指向新实例。 – 2011-05-11 17:19:13

1

你不修改数组的deck变量引用,你只是分配一个新的数组局部变量deck

deck = s2 + s1 + [deck.last] 

上面创建一个新的数组,其内容是s2 + s1 + [deck.last],这然后将新数组分配给本地变量deckdeck原来引用的数组保持不变。如果你想改变数组,那么你需要的东西是这样的:

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

,或者你会失去局部变量deck和非本地阵列,它引用之间的连接。

2

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 
5

就做了Ruby的方式:不要修改原始数组中,返回修改后的数组:

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

呼叫者则返回值分配给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 
相关问题