2008-04-06
■[Ruby] 第 3 回 RHG Strikes Back に参加して Ruby の不思議な実装を見た
第 3 回 RHG Strikes Back に参加しました。ちょっとだけ発表もさせていただきました。
今回は第 4 章のメタクラスあたりについて。複雑すぎです。
以下、得られた知見。
クラスの特異クラスの特異クラスが 1.8 と 1.9 で変わった
RHG には「特異クラスの特異クラスは自分自身である」なんて書いてありますが、そうではないようです。
詳しくは後述しますが、 Ruby レベルでオブジェクトの初期状態における特異クラスを取り出すことは不可能です。以下の実験にはまやかしがあります。
1.8
irb(main):001:0> A = Class.new => A irb(main):002:0> class << A; self; end => #<Class:A> irb(main):003:0> class << (class << A; self; end); self; end => #<Class:#<Class:A>> irb(main):004:0> class << (class << (class << A; self; end); self; end); self; end => #<Class:#<Class:#<Class:A>>>
特異クラスが無限後退します。
1.9
irb(main):001:0> A = Class.new => A irb(main):002:0> class << A; self; end => #<Class:A> irb(main):003:0> class << (class << A; self; end); self; end => Class irb(main):004:0> class << (class << (class << A; self; end); self; end); self; end => #<Class:Class> irb(main):004:0> class << (class << (class << (class << A; self; end); self; end); self; end); self; end => Class
特異クラスの特異クラスは、なんと Class クラスになっています。謎です。
結局何が正しいか
「無限後退に戻すべき」「特異クラスの特異クラスの作成はエラーにすべき」などいろいろな意見がでましたが、まとまってはいません。
追記 (2008-04-13)
Yugui さんの記事にご指摘がありましたが、特異メソッド定義式 (class << obj; end) は、正確には、単純に特異クラスを取り出すという操作だけ行われるのではありません。「obj 特異クラスがなかった場合、特異クラスを作成する」という操作 (副作用?) も同時に行われます。そのため、本来の初期状態における obj の特異クラスは Ruby レベルで取り出すことはできません。実際に Ruby の実装をみると、特異クラスがもつ、自分の特異クラスへのポインタは、初期状態では自分自身をさしています。 特異メソッド定義式を評価した時点で、このポインタが変化してしまい、上記実験結果が得られた訳です。 RHG にある「特異クラスの特異クラスは自分自身である」というのは、初期状態ではそうなっているという意味で正しいです。
Class クラスの子クラスは本来作れないはずだが、実は作れる
Known Bug らしいです。
irb(main):001:0> class A < Class; end
TypeError: can't make subclass of Class
from (irb):1
from :0
irb(main):002:0> A = Class.new(Class)
=> A
irb(main):003:0> A.ancestors
=> [A, Class, Module, Object, Kernel]
irb(main):004:0> A.new
TypeError: wrong instance allocation
from (irb):4:in `new'
from (irb):4
from :0
Module の子クラスは普通に作れる
Yugui さんは「無意味だから禁止すべき」的なことをおっしゃってましたが。
irb(main):001:0> class A < Module; end => nil irb(main):002:0> class B; include A.new; end => B irb(main):003:0> B.ancestors => [B, #<A:0x7fc24>, Object, Kernel]
トラックバック - http://d.hatena.ne.jp/hajimehoshi/20080406/1207490665
リンク元
- 20 http://twitter.com/hajimehoshi
- 19 http://www.hakkaku.net/articles/20080408-183/2
- 19 http://www.starruby.info/ja/contact_us
- 17 http://idm.s9.xrea.com/ratio/2008/04/10/000768.html
- 12 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=BJ0&q=ドワンゴ 社風&btnG=検索&lr=lang_ja
- 11 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4HPNN_ja___JP220&q=Web+Services+関数 呼び出し
- 10 http://d.hatena.ne.jp/
- 10 http://reader.livedoor.com/reader/
- 6 http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/hajimehoshi/20080213/1202830661
- 6 http://www.hakkaku.net/articles/20080408-183