LoginSignup
3
3

More than 5 years have passed since last update.

Object#tapを使ってみて

Posted at

RubyのObjectクラスにある割にはそこまで注目されないメソッドの1つに、#tapがあります。使ってみたところ、個人的にはメリットがあるなと思いました。

返り値にするオブジェクトを組み上げる

よく、

def some_method
  a = []
  a << hoge
  a.concat piyo(:fuga)
  a[0] = false
  a
end

のような、返り値オブジェクトを組み立てるようなメソッドを書く場面がありますが、ときおり最後のaを書き忘れてでたらめなオブジェクトを返してしまうことがあります(Ruby以外では明示的なreturnが必要なので、忘れることはふつう起きませんが)。ここにObject#tapを使うと、

def some_method
  [].tap do |a|
    a << hoge
    a.concat piyo(:fuga)
    a[0] = false
  end
end

のように、変数の生成部が1つのブロックとなります。これなら返り値を書き忘れるということになりませんし、どこでこの変数を変更しているかもはっきりします。

参考リンク:Object#tapでローカル変数を減らす。

定数の生成

文字列1つとかシンプルな配列なら手間なく生成できるのですが、時にはメソッドを呼んだり、ローカル変数を使ったりして巨大な配列やハッシュの定数を作る必要があるかもしれません。とはいえ、定数を破壊的に変更し続けるのは見栄えが悪いですし、定数定義時に使ったローカル変数が散らばってしまうのもすっきりしないものです。

そこで、tapを使えばスコープもローカルにできますし、直接定数を変更するということにもならずに済みます。

SOME_CONSTANT = {}.tap do |h|
  h.merge! a: 1, b: 3
  i = some_method(5)
  h[i] = 100
  h[i + 80] = 7
  h.freeze
end

注意点

性質上、tap内部ではオブジェクトを破壊的変更で変えていく必要があります(Sring#<<Hash#merge!など)。ブロックパラメータに別なオブジェクトを代入しても、うまく動きません。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3