Rubyでメソッドチェーンの途中経過を覗き見るには、Kernel#tapが便利だよね。

(1..10).tap{ |x| puts x.inspect }
        .to_a.tap{ |x| puts x.inspect }
        .select { |x| x % 2 == 0 }.tap{ |x| puts x.inspect }
        .map { |x| x * x }.tap{ |x| puts x.inspect }
 
 # >> 1..10
 # >> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 # >> [2, 4, 6, 8, 10]
 # >> [4, 16, 36, 64, 100]

tapのブロックにはもちろんいろいろな手続が書けるけど、やっぱり出力系メソッドがよく使われると思うんだ。

それならいっそのこと、それらのメソッドがselfを返すようにして、しかも引数を取らないときにはselfが引数になるようにしたら、もっと簡単になるんじゃないかと思ったんだ。

module Kernel
   [:p, :puts].each do |m|
     alias :"__#{m}__" :"#{m}"
     define_method(m) do |obj=self|
       instance_eval "__#{m}__(obj)"
       self
     end
   end
 end

こうしておけば先の例は次のように書けるんだよ。

(1..10).p.to_a.p.select { |x| x % 2 == 0 }.p.map { |x| x * x }.p
 
 # >> 1..10
 # >> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 # >> [2, 4, 6, 8, 10]
 # >> [4, 16, 36, 64, 100]

どうかな?

他の例も示しておくね。

%w(google twitter facebook).map(&:capitalize).puts.map(&:upcase) # => ["GOOGLE", "TWITTER", "FACEBOOK"]
 
 # >> Google
 # >> Twitter
 # >> Facebook
 
 
 require "mathn"
 Prime.each(30).map(&:p)
 
 # >> 2
 # >> 3
 # >> 5
 # >> 7
 # >> 11
 # >> 13
 # >> 17
 # >> 19
 # >> 23
 # >> 29
 
 
 class Array
   def to_h
     Hash[self]
   end
 end
 
 [:GOOG,:YHOO,:MSFT].zip(['google','yahoo','microsoft']).p
                    .to_h.p
                    .each_with_object({}) { |(k,v), h| h[k] = "www.#{v}.com" }.p
 
 # >> [[:GOOG, "google"], [:YHOO, "yahoo"], [:MSFT, "microsoft"]]
 # >> {:GOOG=>"google", :YHOO=>"yahoo", :MSFT=>"microsoft"}
 # >> {:GOOG=>"www.google.com", :YHOO=>"www.yahoo.com", :MSFT=>"www.microsoft.com"}

先の実装だとオリジナルのメソッドにちょっと制限が掛かっちゃうけど1、簡単に途中経過を見れるのはよさそうだよね。

既出のアイディアだったら許してね。

(追記:2011-6-26) やっぱりありました ^ ^; こちらはpの拡張ではないのですが、まあ発想は同じです。

https://github.com/esminc/tapp

面白かったです、特にmapメソッドの間に挟むといいですね。

似たようなやつで、pの内容と一緒にRubyのクラス階層やメソッドを表示する’rubywho’ってのを作ったことがあります。
http://d.hatena.ne.jp/tuto0621/20110616/1308192321 >tuto0621さん
コメントどうも!なるほど、デバッグでオブジェクト情報も全部出しちゃおうってことですね!

  1. 複数の引数が取れないなど


blog comments powered by Disqus
ruby_pack8

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