👋
【Ruby】tapメソッドを試してみた
2025-01-08 00:00
tap メソッドは以前から見かけることはあったが、使い道とかどういう挙動をするのかとかよく分からなかったメソッド。
いつか使うときに調べようと思っていたが、tap を必要とする状況に当たることがなく、またそれを実務のPRレビュー時に見かけることもなかったため、今日まで調べずにいた。
ずっと気になってはいたので、これを気に調べてみようと思う。
tap メソッドとは
self を引数としてブロックを評価し、self を返します。 メソッドチェインの途中で直ちに操作結果を表示するためにメソッドチェインに “入り込む” ことが、このメソッドの主目的です。
とのことで、 self を引数として self を返すのであれば、map や select のようにこのメソッドを通して新たに何かを生み出すわけでは無さそう。
Object のメソッドということで、その値に対しても入り込むことが出来るのはメリットのように見える。
お試しコード
(1..10).tap { puts "original: #{it}" }.
to_a.tap { puts "array: #{it}" }.
select { it.even? }.tap { puts "evens: #{it}" }.
map { it * it }.tap { puts "squares: #{it}" }
# output
## original: 1..10
## array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
## evens: [2, 4, 6, 8, 10]
## squares: [4, 16, 36, 64, 100]
## => [4, 16, 36, 64, 100]
ユースケース
正直使い所がイメージできていないが、もし自分が使うとしたら “デバッグ”。
まさにお試しコードで記述した感じの使い方。
大量のメソッドチェーンで構成された処理では途中途中の値の状況が掴みづらい。
特に、既存コードの調査/修正の際は値が追いづらく苦労することが多い。
その際に、tap を差し込んで値の状況を確認するというのは良さそうに見える。
もしも自分が使うとしたら、 binding.irb
を差し込んで使う。
(1..10).to_a.select { it.even? }.tap { |_| binding.irb }
.map { it * it }.tap { |_| binding.irb }
それ以外の用途は浮かばないのだが、調べてみると、オブジェクトの初期化だったり、処理のワンライン化だったり、で使うみたい。
個人の意見
本番コードについては、無理にtapを使わなくても良いのでは?と思っている。
便利は便利に見えるが、個人的には処理を追いづらい。
tapを用いてブロック化して処理を入り組ませるよりかは、一度変数に格納し、処理を分けて実装するほうが binding.irb を差し込みやすかったり、メンテナンスをしていく中で調査/修正がしやすいのでは?と考えている。
tap を使うことで、ブロック化してスコープを狭めることが出来るという使い方もありそうだが、それはそれとして private メソッドを切り出した方が分かりやすいのでは?と感じた。
自分の場合は、今後もデバッグのとき以外はお世話にならなそう。
自分の理解が甘いだけの可能性があるので、めちゃくちゃ有益な使い方があるなら知りたい。