読者です 読者をやめる 読者になる 読者になる

自動的にEnumerableのメソッドとeach_*をくっつけてみる

ruby

1.9からは組み込みとなるenumratorは便利ですが、あんまり見た目はすっきりしないのでこんなの書いてみました。

require 'enumrator'
module Enumerable
  def method_missing(meth_sym, *args, &block)
    tmp = meth_sym.to_s.split("_")
    after_meth = tmp.shift
    before_meth = tmp.unshift("each").join("_")
    if self.methods.include? before_meth and self.methods.include? after_meth
      enum_for(before_meth.to_sym).__send__(after_meth.to_sym, *args, &block)
    else
      raise NoMethodError
    end
  end
end

これを使うとmap, select, inject, grepなどのメソッドとeach_*なメソッドを勝手にくっつけて呼び出せるようになります。例えば、mapとeach_byteであれば、map_byteのような感じで。mapはこの命名規則に比較的合ってる感じがしますがどうでしょうか?*1

"abcde".map_byte {|i| i.succ.chr }.join
  #=> "bcdef"

"abcde".enum_for(:each_byte).map {|i| i.succ.chr}.join #普通に書くならこんな感じ
  #=> "bcdef"

問題がありそうな点としては、

  • Enumerableのやつじゃないメソッドとeach_*をくっつけることが可能
  • Enumerableのメソッドでも末尾に?がついているやつは出来なさそうだし、仮に出来てもなんか変。
  • each_*のメソッドに引数を与えることが出来ない(each_sliceなど)

といった感じでしょうか。他にもたくさんありそうですがまぁネタなので(ry

*1:素直にmap_with_each_byteとかの方が汎用的な気がしてきた