Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Object#tapで初期値を叩き込んだり、インスタンスの状態を見たりする

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]

と一個メソッドを追加しただけで省略できる点です。