結論
ブロックパラメータには 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
)も必要なんだ、と分かったわけです。
るりま
module function
Kernel.#loop
loop
->Enumerator
loop { ... }
->object
|nil
(中断されない限り)永遠にブロックの評価を繰り返します。 ブロックが指定されなければ、代わりにEnumerator
を返します。
module function Kernel.#loop (Ruby 2.3.0)
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)
-
結論としては、例えば
loop.with_index { |_, i| do_something; break if break_condition; sleep 10 * i }
となります。 ↩