我剛剛遇到一些有趣的枚舉行爲。 Enumerator中的位置似乎存在一些依賴關係 - 一旦您窺視了Enumerable的結尾並且引發了StopIteration,Enumerator就不會注意到Enumerable的擴展。Ruby Enumerator和可枚舉交互:StopIterator依賴
兩個例子說明:
a=[1, 2, 3]
e=a.each
=> #<Enumerator: [1, 2, 3]:each>
2.4.0 :027 > e.next
=> 1
2.4.0 :028 > a.insert(1, 4)
=> [1, 4, 2, 3]
2.4.0 :029 > e.next
=> 4
2.4.0 :031 > e.next
=> 2
OK,到目前爲止,一切都很好。但是這個怎麼樣。讓我們定義一個方法來擴展陣列,當我們打到最後:
def a_ext(a,enum)
enum.peek
rescue StopIteration
a << a[-1] + 1
end
現在,讓我們看到,當我們用它
2.4.0 :012 > a=[1, 2, 3]
=> [1, 2, 3]
2.4.0 :013 > e = a.each
=> #<Enumerator: [1, 2, 3]:each>
2.4.0 :016 > 3.times{e.next}
=> 3
我們已經達到了數組的結尾會發生什麼 - 這麼叫a_ext
到擴展陣列
2.4.0 :018 > a_ext(a,e)
=> [1, 2, 3, 4]
2.4.0 :019 > e.peek
StopIteration: iteration reached an end
???? !!
它看起來像一旦你擊中StopIteration,枚舉器將不會再次檢查是否數組(我猜一般,Enumerable)已被擴展。
這是預期的行爲?一個錯誤?一個特徵?
爲什麼你想要這樣做。好吧 - 通過使用散列,您可以通過傳遞Hash::new
一個塊來設置默認值 - 並且您可以將塊傳遞給Array::new
。但Array::new
作爲參數的塊只有索引作爲鍵,而不是數組和索引(如Hash :: new,其塊將生成散列和鍵)。所以這使得構建一個可以在枚舉數組時通過擴展的數組變得非常難看和困難。
例如,圖像約會日記,你想枚舉通過找到第一個自由的一天。這自然是一個數組,而不是一個哈希(按照它的順序),但是在遍歷時很難擴展。
想法?
恕我直言,你應該避免更新數組,同時迭代它以避免不一致。在你的例子中,你可以使用'find'或'find_index'來代替使用枚舉器。 – sschmeck