Ruby 2.0 リリース週記 (2012/05/21 - 27)
今週も、今週入ったばかりの新機能を紹介します。ちょっと地味というか、細かい話ですが。
今週のニュース: caller の改善で文字列のパースが不要に
背景
かつてより、コールスタックを配列として取り出す機能 Kernel#caller があります。
def foo caller(0).each {|x| p x } end def bar foo end def baz bar end baz
$ ./ruby test.rb "test.rb:2:in `foo'" "test.rb:6:in `bar'" "test.rb:10:in `baz'" "test.rb:13:in `<main>'"
こんな感じ。ここからファイル名だけを取りたいと思ったら、文字列の先頭からコロンまでを切り出す処理が必要です (そういう処理をパースといいます) 。Ruby ではパースは正規表現で簡単にできるものの、盲点が発生しやすいので、あまり好ましいコードではありません。*1
ということで、「パース不要にしてくれ」という声は昔からちょくちょくありました。[ruby-core:13842] [ruby-dev:42345] [ruby-core:24805]
今回導入された機能
そこで我らがささださんが、caller の代わりに使える RubyVM::FrameInfo.caller というメソッドを試験的に導入しました ([ruby-core:45253]) 。文字列の代わりに、RubyVM::FrameInfo クラスのオブジェクトが得られます。このクラスにはファイル名を返す #filename というメソッドがあるので、パースが必要ありません。
def foo RubyVM::FrameInfo.caller(0).each {|x| p [x, x.filename] } end (略)
$ ./ruby test.rb [test.rb:2:in `foo', "test.rb"] [test.rb:6:in `bar', "test.rb"] [test.rb:10:in `baz', "test.rb"] [test.rb:13:in `<main>', "test.rb"]
他にも、行番号を取り出す #line_no やメソッド名相当を取り出す #name などもあります。
考察
長々と書きましたが、一般ユーザが直接使うことはあまりない機能だと思います。というより、個人的には推奨しません。怪しいコードを簡単に書けそうなので。
想定されているユーザは Web などのフレームワーク開発者 *2 などでしょうか。なので、実際のユーザにこの機能の恩恵が届くのは、2.0 リリースより先になるのではないかと思います。プログラミング言語の開発は将来に向けた種まきであることが結構あります。
それ以外には、デバッガやプロファイラの開発に向けた布石と考えられるかもしれません。これからのささださんの活躍にご期待ください。
ちなみに、RubyVM::FrameInfo.caller という名前は長くわかりにくいということで、代替 API の案が募集されています ([ruby-core:45253]) 。また、機能自体に関するコメントも求められていますので、興味のある方は議論に参加されてみるといいと思います。
おまけ: 今のチケット残数
1: matz (137 tickets) 2: nobu (66 tickets) 3: ko1 (56 tickets) 4: akr (31 tickets) 5: mrkn (22 tickets) 6: MartinBosslet, nahi (18 tickets) 8: keiju (15 tickets) 9: kosaki, naruse, usa (13 tickets) 12: authorNari (11 tickets) 13: drbrain, marcandre (10 tickets) 15: knu, tenderlovemaking (9 tickets) 17: seki, sorah (7 tickets) 19: kouji, mame (6 tickets) 21: suke (4 tickets) 22: JEG2, akira, duerst, nagai, shyouhei, takano32, tarui, yugui (3 tickets) 30: shugo (2 tickets) 31: Glass_saga, aamine, kou, metanest, nagachika, ngoto (1 ticket)