2011-05-11 108 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 
相關問題