作者godfat (godfat 真常)
看板Ruby
標題iterator
時間Wed Dec 5 22:31:03 2007
正事幹不了乾脆來胡說八道 O_o
※ 引述《windwofswold ( ◤〔ζ狼ζ〕◢)》之銘言:
: |something| 這是ruby裡面的迭代器(iterator)
個人覺得,說到 iterator 應指 iterator pattern,
也就是一個可以用相同介面 traverse 整個 data structure 的 object.
現在有人把這個東西叫做 external iterator.
而相對於 external iterator, 像 ruby 這樣的 Array#each method,
or foreach loop, i.e. for i in array, 諸如此類的東西,
就叫做 internal iterator, 因為對於外界來說,其 iterator 事實上
是不可見的,是內部的操作。
那麼到底何謂 iterator?
其實可以把他想像成一種 pointer (in C/C++), 有時候也會被叫成 cursor.
還是舉實例最清楚,ruby 也有一種模擬出來的 (external) iterator,
藉由 Generator 這個東西。我之前有發一篇小心得,可以參考一下。
(554 1 2/27 godfat □ [心得] Generator 與 Continuation)
require 'generator'
a = (0...10).to_a
g = Generator.new a
puts g.next # => 0
puts g.next # => 1
puts g.next while g.next? # => 把剩下的 2~9 印出來
之所以說這是模擬的,因為其內部是用 Continuation 做的,
而不是真的有各個容器的 iterator. 真正的 iterator,
一個 data structure 就要有一個新的 class 出來,
用 Continuation 來做的下場就是效率會很慘...。
*
anyway, 這裡就可以很明顯看出所謂 external 和 internal 的差異。
internal 的優點在於,當你只是要做很簡單的事情,internal iterator
使用上會比 external iterator 方便,因為你只需要寫好一個
lambda function (code block) 即可。
a.each{ |i| puts i }
相較於
i = Generator.new a
puts i.next while i.next?
少一個存取的動作。
但是要比彈性,真正的 iterator 保證是強太多了。
首先 internal iterator 難以控制複雜的 traversal,
例如先跑一半,休息,然後再跑一段。
size = a.size
iter = Generator.new a
(size/2).times{ puts iter.next } # 單純跑一半,不要管奇數偶數問題... XD
do_something_interesting
listen_to_next_client # 這邊可以 block 住...
puts iter.next while iter.next? # 把剩下的做完
像是這樣,單用 each 是很難做到的。
而 ruby 的 Generator 其實還是很殘廢的,因為他是模擬的...
也不能 iter.prev 這樣回到前一個。
目前我知道最強的 iterator 應該是 C++ 的 iterator,
他分五種 iterator:
input_iterator
output_iterator
forward_iterator
bidirectional_iterator
random_access_iterator
詳細我就不解釋了... @@ 總之大概可以區分成三種:
可以往前走的、可以往前也可以往後的、可以隨機存取的。
有興趣可以參考這個:SGI STL, 很厲害的 STL 實作
http://www.sgi.com/tech/stl/Iterators.html
可以往後退的,舉一個例子,如何跳著印出?
(如果 generator 可以有 prev 的話...)
while iter.next?
iter.next
puts iter.next
puts iter.prev
end
這樣就可以印出 1 0 2 1 3 2 4 3 5 4 6 5 7 6 8 7 9 8 XD
這例子很爛,跑到最後應該會掛掉 XD
不過總之這樣就可以任意 traverse 整個 data structure,
而無論他是 array, list, hash, tree, etc.
random access 的話就更厲害了,這樣幾乎可以說是任何操作都有辦法做,
也可以將高效率的 sort abstract 出來,只要提供其 random access iterator,
他可以替任何的 data structure 排序。
再另一方面,traverse 中途刪去元素,也是做得到的,即使這樣會破壞原先結構!
只要讓 erase method 本身會傳回下一個正常的 iterator 即可,如把元素為 5 者
刪除:
while iter.next?
iter = iter.erase if iter.next == 5
end
其實這邊我是滿不喜歡用 next 回傳下個元素,
比較希望可以是 .value 取得現在的值,而 .next 往下走這樣。
這邊用 next, 是比較像 Java 的 iterator, 我覺得比較不好用...
因為他變得有些像是強迫你一定要往前走...
而 C++ 的 iterator 就指標味十足,用 operator overloading 操作。
++iter; // 往前走
--iter; // 往後走
iter+5; // 下五個 iterator
*iter; // 取得現在的值
彈性會比較大。
不知道 ruby 1.9 這邊會有什麼改善?目前的 generator 是相當不好用...
我覺得還是需要真正的 iterator 比較好,要用 external 達到 internal
是非常容易的,反之不亦然...
不過理所當然的,external iterator 要實作是相對麻煩得多。
但我覺得划算啦...
--
Hear me exalted spirits. Hear me, be you gods or devils, ye who hold
dominion here:
I am a wizard without a home. I am a wonderer seeking refuge.
Sacrifice
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.58.12
1F:推 ilake:先推再看 XD 12/05 22:52
2F:推 windwofswold:推 有很深~~層的了解XDD 12/06 02:47
3F:推 fcamel:好文一推! 12/07 15:12