Enumerator の作り方

ブロックを付けておくといろいろ出来ます。

new {|y| ... } -> Enumerator

Enumerator オブジェクトを生成して返します。与えられたブロックは Enumerator::Yielder オブジェクトを引数として実行されます。
生成された Enumerator オブジェクトに対して each を呼ぶと、この生成時に指定されたブロックを実行し、Yielder オブジェクトに対して << メソッドが呼ばれるたびに、 each に渡されたブロックが繰り返されます。
new に渡されたブロックが終了した時点で each の繰り返しが終わります。 このときのブロックの返り値が each の返り値となります。

enum = Enumerator.new{ |y|
  (1..10).each{ |i|
    y << i if i % 5 == 0
  }
}
enum.each{ |i| p i }
#=>  5
    10

fib = Enumerator.new { |y|
  a = b = 1
  loop {
    y << a
    a, b = b, a + b
  }
}
p fib.take(10) #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

singleton method Enumerator.new(るりま1.9.3)

ということで、ポイントは「<<」メソッドでローカルブロック変数に配列(というかenumerableな)要素を入れ込むということですね。

無限リストを作る例

# ブロックなしだと succ で進める
# ブロックありだと、ブロックの評価結果を次の要素にする

def builis(start)
  Enumerator.new { |y|
    i = start
    loop {
      y << i
      i = block_given? ? yield(i) : i.succ
    }
  }
end

ruby で無限リストを作る - Qiita

利用例としては、やはりフィボナッチ数列

#みんな大好きフィボナッチ
builis([0,1]){ |x| [x[1], x[0]+x[1]] }.take(15).map(&:first)
#=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
#みんな大好きフィボナッチもう一つ
builis([]){ |x| [x,x[0]] }.take(15).map{ |x|x.flatten.size }
#=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]

ここの内容には関係ないですが、後者は思いつきませんよw