作者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