まつもと ゆきひろです

In message "[ruby-list:13541] iterator <-> cursor (Re: iterator for Dummies)"
    on 99/04/09, Inaba Hiroto <inaba / sdd.tokyo-sc.toshiba.co.jp> writes:

|> Rubyでもスマートな方法はないんじゃないかと思うのですが、スレッド
|> を使えばできないことはないですね。
|
|1.3系なら, スレッドより遅いですけどcallccでもできるみたいです.

おおっ,気が付かなかった.でも,eachが末端でnilを返すことを
期待してません?

参考までに私がスレッドを使って書いた外部イテレータ(カーソル)
を載せておきますです.

--
class ExternalIterator
  def initialize(src)
    @src = src
    @que = []
    first
  end
  def first
    if @thread
      @thread.exit
    end
    @thread = Thread.start {
      for i in @src
	@que.push i
	Thread.stop
      end
    }
    succ
  end
  def succ
    raise 'no more items' unless more
    @que.pop
  end
  alias next succ
  def more
    while @que.empty?
      return false unless @thread.alive?
      @thread.run
    end
    true
  end
  def each()
    while more
      yield succ
    end
  end
end

#<ExternalIteratorサンプル>

def match_items(a, b)
  ia = ExternalIterator.new(a)
  ib = ExternalIterator.new(b)
  i = 0

  item_a = ia.first
  item_b = ib.first
  loop do
    if item_a != item_b
      printf "collections differ on %dth item\n", i
      return
    end
    i+=1
    unless ia.more
      if ib.more
        printf "collections `a' shorter than `b'(size %d)\n", i
	return
      end
      break
    end
    unless ib.more
      if ia.more
        printf "collections `b' shorter than `a'(size %d)\n", i
	return
      end
      break
    end
    item_a = ia.next
    item_b = ib.next
  end
  printf "collections `a' and `b' are same(size %d)\n", i
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})
--

実行結果は以下のようになります.

	collections differ on 2th item
	collections `b' shorter than `a'(size 2)
	collections `a' shorter than `b'(size 2)
	collections `a' shorter than `b'(size 2)
	collections `a' and `b' are same(size 5)
	collections differ on 4th item
	collections `a' and `b' are same(size 2)