咳です。 From: Shin-ichiro Hara <sinara / blade.nagaokaut.ac.jp> > これの callcc 版を考えてみました。まず、Queue 相当のものなんですが、 > バッファがないのでかわいらしく Hole という名前にしました。 いまさら Thread 版を作ってみました。 以前に Thread 間 pipe が欲しくて作ったものに手を加えました。 Pipeクラスは原さんのHoleに相当します。 要素に nil を持てるように番兵 (PipeEOF) を導入しています。 また、複数の Thread が pipe に read/write できます。 ## イテレータとは関係ないっすね。最初はLinda みたいの作りたかったんです。 Pipe は次のように使います。 pipe = Pipe.new Thread.new do for i in 1..5 pipe.write(i) end pipe.close end while (v = pipe.read) != pipe.eof p v end 以下は、Pipe と 外部イテレータです。 -- pipe.rb -- #!/usr/local/bin/ruby require 'thread' class PipeEOF; end class PipeBrokenError<RuntimeError; end class Pipe def initialize(pipelen=1) @enq = Queue.new @buffer = Queue.new for i in 1..pipelen @enq.push nil end @eof = PipeEOF.new # sentinel @done = false end attr :eof def eof?(e) @eof == e end def write(e) @enq.pop if @done @enq.push nil raise(PipeBrokenError, 'closed') end @buffer.push(e) end def read begin v = @buffer.pop ensure @enq.push nil @buffer.push(@eof) if (v == @eof) end end def close @buffer.push(@eof) @done = true end end #=begin # # 外部イテレータにしてみた部分 # if __FILE__ == $0 class Pipe def externalIterator(src) src = src que = Pipe.new Thread.new do for i in src que.write(i) end que.close end que end module_function :externalIterator end def match_items(a, b) begin ia = Pipe.externalIterator(a) ib = Pipe.externalIterator(b) i = 0 loop do item_a = ia.read item_b = ib.read if ia.eof == item_a and ib.eof != item_b printf "collections `a' shorter than `b'(size %d)\n", i return elsif ia.eof != item_a and ib.eof == item_b printf "collections `b' shorter than `a'(size %d)\n", i return elsif ia.eof == item_a and ib.eof ==item_b break elsif item_a != item_b printf "collections differ on %dth item\n", i return end i+=1 end printf "collections `a' and `b' are same(size %d)\n", i ensure ia.close ib.close end end match_items([1,2,3,4,5],[1,2,8,9,0]) match_items([1,2,3,4],[1,2]) match_items([1,2],[1,2,8,9,0]) match_items([1,2],[1,2,8,9,0]) match_items([1,2,3,4,5],[1,2,3,4,5]) match_items([1,2,3,4,5],[1,2,3,4,4]) match_items({1,2,3,4},{1,2,3,4}) match_items([1,2,3,nil,5],[1,2,3,nil,5]) end #=end =begin # # Pipe のテストプログラム部分 # if __FILE__ == $0 pipe = Pipe.new(3) writer = [] for i in 1..4 th = Thread.new { for e in 1..5 pipe.write(e) end } writer.push(th) end reader = [] for i in 1..4 th = Thread.new { begin while (v = pipe.read) != pipe.eof p v end ensure print "died\n" end } reader.push(th) end begin writer.each do |th| Thread.join(th) end pipe.close end reader.each do |th| Thread.join(th) end end =end