26 June 2011
Rubyのpでメソッドチェーンを覗き見よう!
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さん
コメントどうも!なるほど、デバッグでオブジェクト情報も全部出しちゃおうってことですね!
- 複数の引数が取れないなど ↩
blog comments powered by Disqus