«前の日記(2010年06月16日) 最新 次の日記(2010年06月18日)» 編集

Matzにっき


2010年06月17日 [長年日記]

_ [Ruby] Ruby2.0の新機能(かもしれないもの)(3) module operations

注意。このエントリはRuby 2.0に入るかもしれない機能について述べていますが、本機能が本当に2.0に採用されるかどうかは、未定です。

新しめのSmalltlakにはTraitという機能があって、 これは基本的にRubyのmoduleのようなものなのだが、 includeで継承関係をつくる代わりに、そのTraitの機能がクラスに「注入」される。

で、Trait機能の面白いところは、Traitの演算ができる点だ。

つまり、aおよびbがTraitであった時、+演算でaとbの両方の機能を持つ、無名のTraitを作ることができる。

a + b  # => aとb両方の機能を持つTraitを返す

この時、属性(メソッド)に重複があるとエラーになる。

では、重複がある時にはどうするか、というと、Traitから重複するメソッドを取り除く。

a - :foo          # aからfooメソッドを取り除いたTrait
a - [:foo, :bar]  # aからfooメソッド、barメソッドを取り除いたTrait

Rubyにこの「モジュール演算」を取り込むとして、 問題になる点は、定数をどうするか、という点である。 Rubyには名前空間が複数あるので、上記の演算でメソッドの重複を解消できても 定数が重複してしまう可能性はある。

これはたぶん、

  • 定数も重複したらエラー
  • 定数の名称重複を解消する仕組みを用意する
  • または、定数が重複したら結合は潔くあきらめる

ことになるのではないだろうか。

ということで、API案。

  • ModuleをClassのスーパークラスでなくす (または + および - メソッドをClassでundef)
  • Module#+の追加(メソッド、定数の重複はエラー)
  • Module#-の追加
    • 引数がシンボルの時、そのメソッドを削除
    • 引数が配列の時、要素で指定されるメソッドを削除
    • 引数がハッシュの時、メソッドをrename(alias+undef)

当面、定数の名称重複の仕組みは提供しない。

というのも、定数の名称が重複した場合、ほとんどのケースでは単なる削除や名称の置き換えでは解決できそうにないから。もし、本気でやるとしたら、メソッド定義全部をスキャンして、定数への参照部分を書き換えるようなことをしなければならない。それはできれば避けたい。

で、この機能がなんでうれしいかと言うと、「名称重複でエラーが出る」ところ。 includeで関係ないモジュール間で名称が重複しても、継承ラインに並んでしまうので、 エラーにもならず、実際に実行してわけのわからないことになるまで気がつかないが、 モジュール演算を使えば、名称重複によるエラーを(ある程度)事前に検出できる。


«前の日記(2010年06月16日) 最新 次の日記(2010年06月18日)» 編集