この間、RubyのEnumerable#mapを便利にしたEnumerable#mappを紹介したよ。

RubyのEnumerable#mapをもっと便利にしたいよ

module Enumerable
  def mapp(op=nil, *args, &blk)
    op ? map { |e| op.intern.to_proc[e, *args]} : map(&blk)
  end
end
langs = ["Ruby", "Python", "Lisp", "Haskell"]
langs.mapp(:+, 'ist') # => ["Rubyist", "Pythonist", "Lispist", "Haskellist"]
[1, 2, 3].mapp(:+, 10) # => [11, 12, 13]
(1..5).mapp(:**, 2) # => [1, 4, 9, 16, 25]
[[1,2,3,4], [5,6,7,8], [9,10,11,12]].mapp(:last, 2) # => [[3, 4], [7, 8], [11, 12]]
["ruby", "python", "lisp", "haskell"].mapp(:[], -2, 2) # => ["by", "on", "sp", "ll"]

で今日またこれに関連して別のアイディアを思いついたよ。

それはここまで来たらもうmappは要らないんじゃないかってことなんだ。

つまり四則演算に限定されちゃうけど、以下の構文でmapp相当のことができたら面白いと思ったんだ。

%w(Ruby Python Lisp Haskel) + 'ist' # => ["Rubyist", "Pythonist", "Lispist", "Haskelist"]
[1, 2, 3, 4] + 10 # => [11, 12, 13, 14]
[1, 2, 3, 4] + 5.5 # => [6.5, 7.5, 8.5, 9.5]
[1, 2, 3, 4] - 10 # => [-9, -8, -7, -6]
[1, 2, 3, 4] * 2 # => [2, 4, 6, 8]
[1, 2, 3, 4] / 2.0 # => [0.5, 1.0, 1.5, 2.0]
[1, 2, 3, 4] ** 2 # => [1, 4, 9, 16]

割と違和感がないと思うんだけどどうかな?

実装はこんな感じだよ。

class Array
  {:+ => :plus, :- => :minus, :* => :multi}.each do |op, rep|
    alias :"__#{rep}__" :"#{op}"
    define_method(op) do |other|
      case other
      when String, Numeric
        map { |elm| elm.send(op, other) }
      else
        self.send("__#{rep}__", other)
      end
    end
  end
  %w(/ **).each do |op|
    define_method(op) do |other|
      map { |elm| elm.send(op, other) }
    end
  end
end

まあ元のArray#*(Integer)が死んじゃうんだけど..

ちなみにネストした配列でも有効だよ。

[[1,2],[3,4]] ** 2 # => [[1, 4], [9, 16]]
[%w(child neighbor), %w(brother false)] + 'hood' # => [["childhood", "neighborhood"], ["brotherhood", "falsehood"]]

ついでに逆も定義してみるよ。

class String
  alias :__plus__ :+
  def +(other)
    case other
    when Array
      other.map { |o| self + o }
    else
      self.__plus__(other)
    end
  end
end
'ruby' + 'ist' # => "rubyist"
'ruby' + ['ist', 'er', 'mate'] # => ["rubyist", "rubyer", "rubymate"]

まあネタ止まりかな..



blog comments powered by Disqus
ruby_pack8

100円〜で好評発売中!
M'ELBORNE BOOKS