What have you found for these years?

2008-12-04

ruby object model (2)

這幾天想這個 object model 感覺快要腦炸了。奇怪,應該沒那麼難啊,
為什麼一直搞得很困惑??是我變笨了還是其實真的很複雜?

Rubinius 試半天,認為圖應該沒畫錯,事實上應該確實是 Rubinius 的
object model 沒錯。但事實上,在 MRI 和 JRuby 又不一樣...

可以看這兩個 rubinius tickets:
1. calling a 'class' method on an object's metaclass should
invoke the class method of the object's class


2. Kernel and IncludedModule

第一個的重點是:
http://gist.github.com/31903

b = B.new

# false in Rubinius, true in MRI, JRuby
p b.metaclass.superclass.object_id == B.metaclass.object_id

b.meta_def(:cheese) {'cheshire'}

# false in all implementation
p b.metaclass.superclass.object_id == B.metaclass.object_id

1. MetaClass d 的 superclass 不是 D, 而是 MetaClass D !!
2. MRI/JRuby 的 metaclass 會改變!

第一點會造成推斷出來的 method lookup 規則有例外!
第二點則是... Charles L 認為這是合理的
不過我還不太懂他的意思,我只知道使用前和使用後有所差異是詭異的。
就算這應該是 lazily created, 這是當然的,畢竟我們不可成真的產生
窮盡記憶體的 metaclasses. 但是也不能因此先丟個毫無關係的 B 進去吧?
copy on write 仍然必須維持 proxy 的特性啊。我不覺得應該因此改變結構。

第二個重點則是:
http://gist.github.com/30606 的第三則

MRI 和 JRuby 大概是不管怎麼樣,反正插進去就是了。所以他不會影響到已存的
class 們。但是 Rubinius 卻會翻之前的 module 出來重新一個個插進去:
kernel/delta/module.rb: 63~74
if ancestors.include? mod
ancestor = superclass_chain.find do |m|
m.module == mod if m.kind_of?(IncludedModule)
end
ancestor.module.included_modules.each do |included_mod|
included_mod.send :append_features, ancestor
included_mod.send :included, ancestor
end
else
mod.send :append_features, self
mod.send :included, self
end

這個.... 我不知道誰的作法比較好,總之不一樣就是了。

其他一點相關的知識:

=== 是判斷 kind_of? 和 ==(或 eql? equal? 搞不清楚)
但奇怪的是 Fixnum === Fixnum 又是 false.
而 Fixnum === 1 和 1 === 1 又是 true.

思考方法是,你覺得 case 裡面應該要怎麼樣判斷正確?
所以至少就會是 equality, kind_of, 還有 includsion.
例如 (1..10) === 5 也要是 true.

個人建議是不要用這個 method, 那是留給 case 用的。

然後 kind_of? 的判斷並不是看 ancestors,
而是 ancestors 和 metaclass 的 ancestors 都算。
因此 Fixnum.kind_of? Object.metaclass 也會是 true.

這些都算是為了方便所以做的,所以規則有點恐怖...

==
唉,不過我真有點不想再想這個了,覺得快腦炸了。

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0