原です。

In message "[ruby-list:13542] Re: iterator <-> cursor (Re: iterator for Dummies)"
    on 99/04/09, Yukihiro Matsumoto <matz / netlab.co.jp> writes:
|
|まつもと ゆきひろです

|参考までに私がスレッドを使って書いた外部イテレータ(カーソル)
|を載せておきますです.
|
|--
|class ExternalIterator
|  def initialize(src)
|    @src = src
|    @que = []
|    first
|  end

ここの first っていうのは(後ろにもあるけど)、必要なのかなあ。


これの callcc 版を考えてみました。まず、Queue 相当のものなんですが、
バッファがないのでかわいらしく Hole という名前にしました。

class Hole
  def open
    c = nil
    callcc {|c|}
    if @s
      true
    else
      @s = c
      false
    end
  end
  def post(x); callcc { |@s| @r.call(x) }; end
  def get; callcc { |@r| @s.call }; end
  def close
    @closed = true
    post nil
  end
  def closed?; @closed; end
end

# 使用例
h = Hole.new
if h.open
  for i in 1..5
    h.post i
  end
  h.close
end
while x = h.get
  p x
end


そして ExternalIterator ですが、仕様が少し変わっています。

class ExternalIterator
  def initialize(src)
    @src = src
    @que = Hole.new
    first
  end
  def first
    if @que.open
      for i in @src
        @que.post i
      end
      @que.close
    end
  end
  def succ
    raise 'no more items' unless success?
    @que.get
  end
  alias next succ
  def success?
    not @que.closed?
  end
  def each()
    loop do
      x = succ
      break unless success?
      yield x
    end
  end
end

def match_items(a, b)
  ia = ExternalIterator.new(a)
  ib = ExternalIterator.new(b)
  i = 0
  loop do
    item_a = ia.next
    item_b = ib.next

    if !ia.success? and ib.success?
      printf "collections `a' shorter than `b'(size %d)\n", i
      return
    elsif ia.success? and !ib.success?
      printf "collections `b' shorter than `a'(size %d)\n", i
      return
    elsif !ia.success? and !ib.success?
      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
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,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})


一応結果はいいみたいですが、間違ってるかも。