4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kernel.#loopにEnumerator#with_indexを付けるときの注意点

4
Posted at

結論

ブロックパラメータには Kernel.#loop のパラメータも用意すること。
というか、Enumerator#with_index がレシーバに対応するブロックパラメータをも必要とする、ということ。

pry(main)> loop.with_index { |_, i| puts i; sleep 1 }
0
1
2
3
^CInterrupt: 

_Kernel.#loop のパラメータ、iEnumerator#with_index のパラメータです。

経緯

ループしながら待ち時間を徐々に長くするにはどうすれば良いかな、と思ったのがきっかけです1

loop.with_index do |i|
  p i
  sleep 1
end

を実行してみると nil しか返ってきません。
Kernel.#loopEnumerator を返すはずなのになあ、と思いつついろいろいじくりました。

最終的に、次のようにしたときに気付きました。

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)](http://docs.ruby-lang.org/ja/2.3.0/method/Enumerator/i/with_index.html)
  1. 結論としては、例えば loop.with_index { |_, i| do_something; break if break_condition; sleep 10 * i } となります。
    さて、試しに

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?