tapはselfをブロック引数としてアレコレしてくれます。
配列なら
Array.new.tap do |ary| ary[0] = 1 ary[1] = 3 end #=> [1, 3]
ハッシュでも
Hash.new.tap do |h| h[:first] = 1 h[:second] = 2 end #=> {:first=>1, :second=>2}
インスタンス変数だって
class Foo attr_accessor :a, :b, :c end Foo.new.tap do |foo| foo.a = 'a' foo.b = 'b' foo.c = 'c' end
更に、メソッドチェインの中に入り込んで処理を強要する事もできます。
...というか、公式としてはこれが主目的なんだそうです。
(1..10).tap {|x| puts %Q(Base: #{x.inspect})}.to_a.tap {|x| puts %Q(Arrays: #{x.inspect}) }.select {|x| x%2==0 }.tap {|x| puts %Q(Even: #{x.inspect})} #>> Base: 1..10 #>> Arrays: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] #>> Even: [2, 4, 6, 8, 10] #=> [2, 4, 6, 8, 10]
さらに...個人的に素敵だと思った用法は
hoge = (1..1000).lazy.select {|x| x % 13 == 0}.take(5).to_a p hoge #=> [13, 26, 39, 52, 65]
なんて一度使いの変数に捩じ込んでやっていたのを
(1..1000).lazy.select {|x| x % 13 == 0}.take(5).to_a.tap {|x| p x} #=> [13, 26, 39, 52, 65]
と一個メソッドを追加しただけで省略できる点です。