Ruby 2.0のリリースマネージャー、遠藤侑介氏が、直近のRuby 2.0.0フィーチャーフリーズ、最初のプレビューリリース、そしてリリース目標日は2013年2月24日であることをアナウンスした。2月24日というのはRuby 20歳の誕生日でもあり、2.0のリリースにはぴったりだ。
新機能のまとめはRubyのNEWSファイルとイシュートラッカーにもあがっている。数ある変更のなかでも、Rubyプログラマにとって一番インパクトがあるのは、キーワード引数とRefinementsだろう。
キーワード引数
メソッド引数としてハッシュを渡す代わりに、Ruby 2.0ではキーワード引数がきちんとサポートされる。以下はRubyのユニットテストからの引用だ。
def f1(str: "foo", num: 424242) [str, num] end def test_f1 assert_equal(["foo", 424242], f1) assert_equal(["bar", 424242], f1(str: "bar")) assert_equal(["foo", 111111], f1(num: 111111)) assert_equal(["bar", 111111], f1(str: "bar", num: 111111)) assert_raise(ArgumentError) { f1(str: "bar", check: true) } assert_raise(ArgumentError) { f1("string") } end
これらはデフォルト値のある引数にだけ動くことに注意しよう。新しい構文と従来の引数との動作については、Rubyのユニットテストに例がある。
Refinements
Refinementsはパッチが適用されるスコープを限定することで「モンキーパッチング」をより安全にすることを狙っている。Matzによって投稿された以下のサンプルでは、/ オペレータはMathNモジュールがインクルードされたあとFixnumでのみ利用できる。
module MathN refine Fixnum do def /(other) quo(other) end end end class Foo using MathN def foo p 1 / 2 end end
Yehuda Katz氏は、実際にRefinementsがどう使われるのか、ブログに詳しく書いた。Refinementsは現在Ruby 2.0ブランチに含まれているが、パフォーマンス問題のために追い出される可能性がある(詳しくはオリジナルのフィーチャーリクエストを参照)。
InfoQはRuby 2.0についてさらに学ぼうと、遠藤侑介氏と話す機会を得た。ユーザにとって最大の変化は何だと思っているか聞いてみた。
Refinementsは言語に対する一番基本的な新機能ですね。これはRubyのモジュール化に新たな概念をもたらします。多くの人はこれを利用して、「モンキーパッチング」というバッドプラクティスを置き換えられるでしょう。この機能はまだ進化中であることに注意してください。いわば、それ自身まだunrefinedだということです。これからさらに経験を積んで、成熟していくでしょう。(もちろん、私たちは可能な限り互換性を尊重します)
キーワード引数は一番目を引く機能かもしれません。実際のところは、そう大きな機能ではなく、シンタックスシュガーにすぎません。実務的な観点からは、コードをきれいにするのに非常に役立つでしょう。
Enumerator#lazyは怠惰なプログラマ(関数プログラミングに精通した人)にとって長年の夢でした。この機能はリストの遅延評価として役立ちます。
Module#prependは実は一番使える機能かもしれません。Railsの汚い"method_alias_chain"を、モジュールを使ったもっときれいな仕組みに置き換えます。
これらの機能について詳しく学ぶには、RubyConfでの松田明氏のプレゼンテーションを見るとよいでしょう。
もちろん、パフォーマンスもかなり改善されています。新機能に関心のない人にとって、これが一番関心のある変更かもしれませんね。
InfoQ:1.9から2.0へのアップグレードは1.8から1.9へのアップグレードよりも簡単ですか?
「普通」のプログラムは変更なしに動くと思います。2.0を設計するときには、1.9とのソース互換性にかなり注意を払いました。
とはいえ、若干変更もあります。実際に互換性問題を引き起こすことはないと思っていますが、私たちが間違っている可能性もあります。公式リリース前に問題がわかれば、喜んで再検討します。
ですから、どうかプレビューリリースとRCリリースを試してください、そして何か気づいたことがあれば是非報告してください。私たちは皆さんからのフィードバックにとても感謝しています。
InfoQ: ユーザが遭遇するかもしれない、潜在的な非互換性はありますか?
先ほども述べたように、実際のところ、いくつか非互換性があります。それについてはNEWSファイルを見るとよいでしょう。たとえば、
私たちはプレビューリリースとRCリリースのフィードバックを集めて、公式の2.0.0リリースに合わせて、アップグレードのためのシンプルなガイダンスを作りたいと思っています。
- Object#respond_to?はデフォルトでprotectedメソッドにfalseを返します。
- Kernel#systemと#execはデフォルトで非標準ファイルデスクリプタを継承しません。
- Object#inspectはデフォルトで#to_sを呼び出しません。
遠藤侑介氏が述べたように、パフォーマンスが改善されているようだ。そして、Rubyのメモリ使用量を減らすため、新しいビットマップマーキングGC (InfoQでは開発者の中村成洋氏に話を聞いた) が2.0リリースに含まれる予定だ。どう動くのかもっと学びたければ、Rubyのガベージコレクションについて詳しく書かれた素晴しい記事があるので読んでみよう。
以下に、Ruby 2.0に入る予定の興味深い新機能と重要な変更を挙げておく。
- アプリケーションを実行時にプロファイルするためのDTraceプローブ
- Enumerableでオペレーションを遅延実行するためのEnumerable#lazy
- Perl 5.10で導入された新機能をサポートする正規表現ライブラリOnigmoの改善
- モジュールメソッドをほかのモジュールやクラスに移動させることができるMethod transplanting
- モジュールをprependするModule#prepend。これによりprependされたモソッドは既存のメソッドをオーバーライドする
- Object#respond_to?はもはやprotectedメソッドをチェックしない
- CGIにおけるHTML5サポート
Ruby 2.0.0-preview1リリースをダウンロードして、是非感想を聞かせてほしい。