🖥

Ruby - ArrayとEnumerator の違い

に公開

たとえば Integer#times は配列ではなく Enumeratorを返してくる

3.times # => #<Enumerator: ...>

なぜなのだろう。

Enumerator が使われる理由

  • 配列生成してそれを保持するとメモリが食われるため大量の不向き
  • そもそも配列では実現できない処理がある

このあたりが理由ではないだろうか。
と思ってあとからググったら同じ理由を述べる記事が複数見つかったので当たっていたようだ。

配列のeachで実現できない処理というのは次に述べるように例えば無限回数の処理とか。

無限回数の繰り返し

無限回数の繰り返しをおこなう loop メソッドも Enumerator だ

loop # => #<Enumerator: ...>

これを配列で実現しようとするとどうだろう?
無限個数の配列をあらかじめ作るわけにはいかない。(作れない)

すなわち Enumerator が必要だ。

Enumerator の挙動

たとえば Enumerator には next メソッドがあり each せずとも1個ずつ処理することが出来る。

t = 3.times

t.next { |i| p i } # => 0
t.next { |i| p i } # => 1
t.next { |i| p i } # => 2
t.next { |i| p i } # StopIteration: iteration reached an end

何かのライブラリのクラス(のインスタンス)で next するたびに外部APIにリクエストするものも見たことがある気がする。

この場合もあらかじめ全ての外部APIリクエストをおこなっておくことは出来ないというか極めて非効率なので Enumerator で実装されているのは理にかなっているのだろう。

実装としての正しさ

たとえば 100.times の返り値で Array.new(100) のように100個のnilが返ってきたら普通にびっくりしないだろうか。
やりたいことは 100回の繰り返し処理であって100個の配列ではないためだ。

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2023-09-04

Discussion