フィルタ (2)

長い道のりだった……、id:babie:20050921:p7 の続き。って9月かよ!


PHPSmartyPerl の TT のように 「|」 でフィルタチェインができたらええなー、と考えてたやつ。


カリー化を使ったお! 使えるお! もっと簡単な実現方法があっても気にしない。カリー化使えて満足。

#!/usr/bin/ruby

# this method was written by HORIKAWA Hisashi.
# See: http://www.nslabs.jp/ramble-200601.rhtml#28
def currying(name, *args)
   if name.kind_of?(Proc) or name.kind_of?(Method)
      m = name
   else
      m = method(name)
   end
   arity = m.arity >= 0 ? m.arity : -m.arity - 1
   if arity <= args.size
      m.call(*args)
   else
      lambda {|*a| currying(name, *(args + a))}
   end
end


# below code written by babie.
class String
   def | m
      m.call(self)
   end
end

class Filter
   def sigh str
      "..." + str + "..."
   end

   def sandwich(bread, str)
      bread + str + bread
   end

   def headtail(prefix, suffix, str)
      prefix + str + suffix
   end
end


if __FILE__ == $0
   # curry
   curry_sandwich = currying(Filter.new.method(:sandwich), "---")
   p "ahaha" | curry_sandwich

   # def
   def def_sandwich(*arg)
      currying(Filter.new.method(:sandwich), *arg)
   end
   p "ihihi" | def_sandwich("---")

   # eval
   eval <<-EVAL
      def eval_sandwich(*arg)
         currying(Filter.new.method(:sandwich), *arg)
      end
   EVAL
   p "ufufu" | eval_sandwich("---")

   # final
   class Dummy; end
   (Filter.instance_methods - Dummy.instance_methods).each do |name|
      eval <<-EVAL
         def #{name}(*arg)
            currying(Filter.new.method(:#{name}), *arg)
         end
      EVAL
   end
   p "fufuf" | sigh
   p "ehehe" | sandwich("---")
   p "ohoho" | headtail("<<<", ">>>")
end

出力:

$ ruby filter.rb
"---ahaha---"
"---ihihi---"
"---ufufu---"
"...fufuf..."
"---ehehe---"
"<<<ohoho>>>"

ここまでくれば Rails に載せるのも、そう遠くはあるめぇ。


これで心おきなく仕事(PHP)に戻れる。(をぃ