イテレータを便利にするenum_for

ruby 1.8.7 からenumerator が組み込みで使えるようになった。enum_for がデフォルトで使える。

enum_for

Enumerable に定義されているメソッドの多くはinclude 先のクラスのeach メソッドを使って実現されている。
例えばmap の実装は以下のようなイメージ。

class Array
  def _map
    result = []
    
    each do |e|
      result << yield(e)
    end

    result
  end
end

[1, 2, 3]._map{|x| x*2}  # => [2, 4, 6]


enum_for を使うと、内部で利用されるeach の代わりに他のメソッドを使うことができる。定番はeach_with_index とmap のコンボ。

# Array#map 内で使われるeach をeach_with_index に置き換える
[:a, :b, :c].enum_for(:each_with_index).map  # => [[:a, 0], [:b, 1], [:c, 2]]


イテレータはブロックを渡されないとenum_for(method) の結果を変えすので以下のに書ける。

[:a, :b, :c].each_with_index.map  # => [[:a, 0], [:b, 1], [:c, 2]]


enum_for かっこいし、便利っぽいけど、まだ実際に使ったことない。いい使い道ないかな。

hash = {:a => 1, :b => 2, :c => 3}
hash.each_value.inject{|sum, v| sum += v}  # => 6


うーん。微妙。
なんか、内容とタイトルが矛盾してしまった。