結論
ブロックパラメータには Kernel.#loop のパラメータも用意すること。
というか、Enumerator#with_index がレシーバに対応するブロックパラメータをも必要とする、ということ。
例
pry(main)> loop.with_index { |_, i| puts i; sleep 1 }
0
1
2
3
^CInterrupt:
_ が Kernel.#loop のパラメータ、i が Enumerator#with_index のパラメータです。
経緯
ループしながら待ち時間を徐々に長くするにはどうすれば良いかな、と思ったのがきっかけです1。
loop.with_index do |i|
p i
sleep 1
end
を実行してみると nil しか返ってきません。
Kernel.#loop は Enumerator を返すはずなのになあ、と思いつついろいろいじくりました。
最終的に、次のようにしたときに気付きました。
pry(main)> l = loop.with_index
# => #<Enumerator: ...>
pry(main)> l.next
# => [nil, 0]
pry(main)> l.next
# => [nil, 1]
pry(main)> l.next
# => [nil, 2]
pry(main)> l.next
# => [nil, 3]
ああ、なるほど Enumerator#with_index のレシーバである Kernel.#loop に対応するブロックパラメータ(ここではブロックを付けていないので nil)も必要なんだ、と分かったわけです。
るりま
>##instance method `Enumerator#with_index` `with_index(offset = 0) {|(*args), idx| ... }` -> `object` `with_index(offset = 0)` -> `Enumerator` 生成時のパラメータに従って、要素にインデックスを添えて繰り返します。 インデックスは `offset` から始まります。 ブロックを指定した場合の戻り値は生成時に指定したレシーバ自身です。 生成時のパラメータに従って、要素にインデックスを添えてブロックを繰り返します。 インデックスは 0 から始まります。 [instance method Enumerator#with_index (Ruby 2.3.0)](http://docs.ruby-lang.org/ja/2.3.0/method/Enumerator/i/with_index.html)##module function
Kernel.#loop
loop->Enumerator
loop { ... }->object|nil
(中断されない限り)永遠にブロックの評価を繰り返します。 ブロックが指定されなければ、代わりにEnumeratorを返します。
module function Kernel.#loop (Ruby 2.3.0)
-
結論としては、例えば
loop.with_index { |_, i| do_something; break if break_condition; sleep 10 * i }となります。
さて、試しに ↩