Generator
Generatorを使うと、内部イテレータ(Array#eachみたいな、渡されたブロックに対して要素を1つづつコールバックするタイプのイテレータ)を外部イテレータ(Java見たいな、hasNext,nextで要素を取り出すイテレータ)に変換できます。
array = ["1", "2", "3"] # 内部イテレータで要素を列挙 array.each {|i| puts i } # generatorで外部イテレータに変換して要素を列挙 puts "---" g = Generator.new( array ) while g.next? puts g.next end
実行結果です。
1 2 3 --- 1 2 3
で、気になるのは性能。ドキュメントには「実装に callcc を使っているので遅いです。」と書かれているのですが、実際のところどうなのか、簡単に計測してみました。
require 'generator' require 'benchmark' array = [].fill(1, 0..10000) Benchmark.bm(13) {|x| x.report("each : ") { array.each {|i| } } x.report("generator : ") { g = Generator.new( array ) while g.next? g.next end } }
実行結果です。
user system total real each : 0.010000 0.000000 0.010000 ( 0.009000) generator : 6.158000 0.030000 6.188000 ( 6.301000)
うーん、かなり違うな。