Ruby 25 周年記念パーティでデバッグ出力を行う gem つくってきた

今日 2018年2月24日は Ruby が誕生してちょうど 25年目!
ということで記念パーティに行ってきました。
まあなんとなく行ってきたんですが、別に偉い人の話を聞いてもしょうがないので会場ではひたすら Ruby のコードを書いていました。人の話を聞いているよりもコードを書いている方が有意義なのじゃ
そして、ついこの間 2.5 がリリースされたと思ったらもう Ruby 2.6.0-preview1 が出ていますね…早い…。
ちなみにこのバージョンではわたしが投げたパッチも取り込まれているようでよかったよかった。
そんなわけで Ruby 25周年記念でつくったデバッグに便利そうな gem を公開しました。

インストール

$ gem install binding-debug

binding-debug とは

例えばデバッグ出力をする際に 変数名 : 値 みたいな形で出力されてほしい事があると思います。
しかし、このような形式で出力したい場合、毎回自分で変数名を記述する必要があります。

hoge = 42
# 自前で毎回こんな感じの出力フォーマットを定義する必要がある
puts "hoge : #{hoge}"

これをどうにかしたかったのでいい感じにデバッグ出力できる gem をつくりました。

使い方

デバッグ出力を行いたいコンテキスト情報(変数名とか)を取得するために Kernel.#binding を利用します。
以下のようにして Binding#puts に対して評価したい変数(式)を渡すことで 変数名(式) : 評価した値 みたいな感じで出力されます。

require "binding/debug"

# 要 refinements
using BindingDebug

hoge = 42
binding.puts "hoge"
# output: "hoge : 42"

# Binding#p だと Kernel.#p で出力
binding.p "hoge"
# => "hoge : 42"

また、複数の式を評価したい場合は、%{} 記法を利用することが出来ます。

# %{} を利用すれば以下のように書くことも
def plus a, b
    a + b
end

foo = "homu"
binding.puts %{
  foo.to_s.upcase
  plus 1, 2
  (0..20).to_a
  foo.class.name
}
# output:
# foo.to_s.upcase : HOMU
# plus 1, 2 : 3
# (0..20).to_a : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
# foo.class.name : String

思ったよりもいい感じに書けますね。

経緯

元々は instance_eval + method_missing で以下のように『ブロック内で呼び出されたメソッドに対してフォーマット出力する』ことを考えていました。

hoge = 42
# method_missing でいい感じに hoge の呼び出しに対してフックしていい感じに出力する
binding.puts { hoge }

しかし、上記の場合、hoge という呼び出しが『メソッド呼び出し』ではなくて『キャプチャした変数』を優先して呼び出してしまうため意図した呼び出しが出来ませんでした。

hoge = 42
# 明示的にレシーバを付けて呼べばメソッド呼び出しとして評価されるので method_missing で呼び出せるが…
binding.puts { self.hoge }

会場でつくっている途中でこの問題に気づいて「うーん、どうしようかな…」と悩んでいたら偶然にも会場に来ていた強い Rubyist の人に「%{} 記法を使うのはどうだろうか、ブロックっぽいし」と助言を貰ってシンプルに文字列を渡して評価する実装にしました。
一応、

homu = "homu"
binding.puts { self.homu.upcase }

みたいにチェーン呼び出しにも対応させる実装は書いたんですが、文字列を評価するようにするほうが実装もずっとシンプルになりとてもよい。
ぶっちゃけ勢いで雑に公開したので実際に使ってみて問題がいろいろと治す予定ではあります。
っていうか、探せば類似 gem はありそうだけどそんなの気にしない!

所感

と、言うことで 25周年記念パーティ会場でせっせとつくった gem でしたー。
わたしは Ruby 歴 3年ぐらいのにわかですが、みなさん Ruby 愛が強くてすごいですね。
今後は mruby なんかもいい感じに盛り上がってほしいと思っています(その前に cruby と mruby で仕様がぶれているのをどうにか…
わたしは Rails が全く出来ませんし RubyRails みたいな世の中は本当にクソだなと心の底から思っていますが、Ruby 自体は書いていてとても楽しい言語なので、これからも役に立たない面白いコードやライブラリなんかを書いて行きたいです!!!
Ruby は書いていて楽しいのでみんな Ruby 沼んいハマろう!!

ちなみに関係ありませんが今年は C++ 35周年の年でもあります!
みんな C++ ちゃんも祝ってあげよう!!!
そんなわけで Ruby パパの Matz、Ruby コミッタ、関係者のみなさん、楽しい Ruby をありがとうございます!