外部イテレータについてメモ。

require 'generator'

g = Generator.new([1,2,3])

while g.next?
  puts g.next
end

ってやれば、Rubyで外部イテレータが使える。

で、2つ以上をイテレートしたいときには、

require 'generator'

s = SyncEnumerator.new([1,2,3], ['a', 'b', 'c'])

s.each do |row|
 puts row
end

ってやってあげればOK。どっちかが短い場合はそこにnilが入る。

これを外部イテレータなしでやるなら

[1,2,3].zip(['a','b','c']).each do |row|
  puts row
end

とかやってあげればいいんだと思う。ただこの場合はzipされるほう*1が長くなきゃ最後まで行かない。

外部イテレータの方がきれいだけど、実行速度は遅いです*2。継続を使っているから。

以上、ほぼプログラミング言語 Ruby リファレンスマニュアルプログラミング言語 Ruby リファレンスマニュアルからのネタでした。

ちなみに1.9なら

e = [1,2,3].each

loop do
  puts e.next
end

でOKです。要素がなくなったら nextがStopIterationを投げてloopがそれをうけとるらしい*3
loopじゃなくてwhile true でもいいのかなーと思ってためしたらだめだった。

*1:これでいうと[1,2,3]

*2:手元のMacBookでは1000回回すだけで2秒くらいかかった

*3:Route 477(2007-12-15)より