前田です。 At Fri, 9 Apr 1999 09:24:01 +0900, 助田 雅紀 <masaki.suketa / systemplaza.co.jp> wrote: > 内部イテレータを使って外部イテレータを普通は実装できないが > 実は,Ruby ではできるという部分は私にもよくわかりません. # 以下、内部イテレータをイテレータ、外部イテレータをカーソルと呼 # びます。 カーソルからイテレータへの変換は簡単ですよね。 例えば、nextで次の要素を返し、要素がなくなったらnilを返すカーソル があったとすると、 class Enumerator def initialize(cursor) @cursor end def each while obj = @cursor.next yield(obj) end end end c = Cursor.new([1, 2, 3]) e = Enumerator.new(c) e.each do |i| p i end # C++ならブロックの代りに関数ポインタや関数オブジェクトを渡すこと # になるでしょう。 逆に、イテレータからカーソルへの変換は普通できません。 Rubyでもスマートな方法はないんじゃないかと思うのですが、スレッド を使えばできないことはないですね。 require "thread" class Cursor def initialize(iter) @iter = iter @finished = false @queue = Queue.new Thread.start do iter.call do |obj| @queue.push(obj) end @queue.push(nil) # @finished = trueだとデッドロックになりそ # うな気がする end end def next if @finished return nil else obj = @queue.pop @finished = true if obj.nil? return obj end end end c = Cursor.new([1,2,3].method(:each)) while obj = c.next p obj end まつもとさんがおっしゃっているのはもっとスマートな方法なのかも...。 -- 前田 修吾