What have you found for these years?

2009-03-10

ruby object model (0)

上次聊過的 rubinius,
http://blogger.godfat.org/2008/12/rubinius-slide.html
一直說要詳細描述一下裡面的 object model, 不過一直遲遲沒有動手。
那就趁這個機會寫一下好了,雖然我不知道現在這樣能不能寫得清楚流暢,
但總之有個第一版總比什麼都沒有好,這樣吧。

請看這張圖:

這是我用 Visual Paradigm 的 UML 程式大概畫的,
當然,不是照 UML 的規格,只是拿這來畫圖表似乎比較方便。
因為會需要不斷調整各個方塊和箭頭的位置,用投影片軟體會做到瘋掉。

就像投影片第 123~127 張,其實我們大致可以把 object 分成三群,
分別是 instance 層級、class 層級與 meta-class 層級。
投影片中的第一個圈是 class 層級,第二個圈也是 class 層級,
而第三個圈則是 meta-class 層級。這裡沒有畫出 instance,
因為那比較簡單,大家都知道。而第二和第三個圈,雖然都是 class,
不過由於第二個圈,也就是 Module, Class, 和 MetaClass 比較特別,
所以投影片上才特別畫出來。至於這裡則先不要看那兩個圈有什麼不一樣。

雖然不一樣,但套用 Ωmega 的說法:
[quote="Programming in Ωmega"]
All values are classified by types that are classified by *0.
All types are classified by kinds that are classified by *1.
All kinds are classified by sorts that are classified by *2,
etc.
[/quote]
在這裡,values 就是 instance, types 就是 class, 而 kinds 就是
meta-class, 至於 sorts? Ωmega 會無窮延伸下去,直到 *∞, 而 ruby
則會收斂至 meta-class. 所以 ruby 裡就沒有類似 sorts 的東西。

但事實上,當然沒辦法一對一對應這種概念。ruby 有一個設計原則,
就是方便性比合理性重要。所以他的 consistency 並不高,instance
是隸屬於 class 沒錯,而 meta-class 卻也仍然是隸屬於
class, 並不是 meta-class, 更不是 meta-meta-class;
同時,他們自己也是 instance.

所以用很白話的說法,ruby object model 遵守兩個原則:

1. 所有的值(value)都是 instance.
2. 所有的 instance 都來自某個 class.

如果你發現推導出來的結論,違反這兩個原則的話,
不管這個推導對不對,全部都不算數。因為,ruby 希望的是
符合人性,如果人性是矛盾的,則 ruby 的規則也是矛盾的。

雖然我們會說有 meta-class 的存在,是 class 的 class,
但 meta-class 事實上仍然是一個 class. meta-class 只是
一個解釋上的概念,而並不是真的有這樣的概念存在。

也因此,我們可以很簡單把所有的東西都視為同一件事,
很簡單地做到幾乎不受任何限制的 polymorphism,
不會像 Agda2 那樣碰到 Set1, Set2, Set∞ 之類的問題...

ruby 的 meta-meta-meta-class 並不是像那樣的東西。
而到底哪一種比較好呢?我認為無窮延伸下去是比較合理的。
但現實上無窮延伸下去到底有什麼用,可以帶來什麼好處,
可能沒多少個人有辦法回答吧...

所以我會說 ruby 的這種方式比較不合理,但比較有用。
可是究竟有用在哪?我們真的需要 meta-meta-meta-class 嗎?
我還沒想到有什麼非常實際的用法,通常 meta-class 就足矣。

*

回到本文的圖片。白框表示該 instance 的 class,
黑框表示該 instance 的 meta-class. 藍框則是 parent,
是 class 才會有的屬性。而 meta-class 實際上也是 class,
所以當然也會有 parent. 沒有 parent 的,只有 instance.

class hierarchy 最直接影響到的,當然就是 method dispatch.
所以投影片裡,下一個也就是講 method dispatch.

因為 ruby 並沒有 multiple inheritance, 所以不會有可怕的
ambiguous 問題。一個 class 的 method dispatch path,
最終一定可以拉成一條直線。

這條直線就是從 meta-class 開始走。
隨後則是沿著 parent 這條路走。

instance => meta-class => parent => ... => parent

這就是唯一的那條 dispatch 路線了。對於不管是哪個 instance
皆然。所以對於 class 當然也是這樣的。於是可以開始探討那個
最早的 meta-class 是什麼東西了?

lukhnos 說他覺得這件事說得最好的,是 David A. Black 的
Ruby for Rails 這本書。後來因為好奇翻了一下,不過沒找到
是在哪裡描述這段,然後就沒耐心了..........

他還說這聽起來與 Smalltalk 的 spec 上的描述差不多,
不過這個我一直沒有找時間去 review 一下,改天有機會吧。

meta-class 的存在,大抵上是為了兩件事:

1. singleton method
2. class method

在 prototype-based programming languages 裡面,
singleton method 是一件很自然的事。因為沒有 class,
所以我們當然得對所有的 instance 定義「獨特」的 method.
事實上,這也是為什麼我認為 ruby 是可以寫得很有 prototype 的味道。

由於 singleton method 的獨特性,我們當然會期望他是
the most special(important) method, 所以當然是他去
override 其他所有的 method. 因此,他必然得是第一個被 lookup.

接下來,我們當然得去該 instance 的 class 去搜尋,
然後則是 parent, parent, parent, etc. 那麼與其把路徑做成:

instance => meta-class
class => parent => ... => parent

變成要走兩條路,不然就把他們接起來?變成:

instance => meta-class => parent => ... => parent

那麼我們就得到一個 instance 的 meta-class 的 parent,
其實就是該 instance 的 class! 如圖 MetaClass d 的
parent 其實就是 D. 這邊是我最早提到三個圈裡面的第一個圈,
instance 層級的部份。對於 instance, 他的 meta-class 的
parent, 就是其 class.

至於第二個原因,class method, 則是 class 層級的事。
既然什麼東西都是 instance, class method 又為什麼不是
instance method? 事實上,class method 確實就是
instance method, 只是觀察的角度不同而已。

class Human; def self.create; end; end
class Mutant < Human; end

Human 的 create, 就是 Human 的 class
(其實是 meta-class) 的 instance method.

但是其實 Human 的 class 並不是真的 Human 的 class.
Human.class 的結果會是 Class, 因為我們認定所有的 class
的 class 都是 Class, 這就是某種矛盾。因為事實上,真正的
class 是 MetaHuman 才對。

這樣做的理由很簡單。因為如果 Class 是 Human 真正的 class,
那你定義 Human.create 時,事實上就會導致 Fixnum.create 也有效。
因為 Fixnum 與 Human 同樣都是 Class 的 instance!!

所以為了人性(矛盾)的 class method, 我們不能把 Class 當真正的
class. 於是 MetaHuman 被插進來了,create 這個 method, 會被放入
MetaHuman, 然後 Human.create 就得以成立;Fixnum.create 不成立。
因為 Fixnum 跟 MetaHuman 並沒有任何關係。

也就是說,class method 是定義在其最獨特的 meta-class 中,
跟 singleton method 一樣!

於是 class method lookup, 也可以依照同樣的路線:

class => meta-class => parent => ... => parent

這些 parent, 很顯然其中一個就會是 Class.
而為了使得 Mutant.create 也成立,也就是說,super-class 的
class method, 也可以是 derived-class 的 class method.
那麼,MetaMutant 的 parent 就會是 MetaHuman.
依照上述的路線,Mutant.create 會先搜尋 MetaMutant,
發現找不到,然後去其 parent 也就是 MetaHuman 尋找!

回到我們的圖,這裡 MetaHuman 就是 MetaClass C,
而 MetaMutant 就是 MetaClass D.
C 的 class method, D 也看得到。

往上繼續追,MetaClass C 的 parent 是 MetaClass Object,
因為 Class 也是 Object, 所以 Object 的 class method,
C, D 也都看得到。

注意到了嗎?這裡就可以看出投影片圈圈。class 有的 hierarchy,
meta-class 也有。下面是怎麼繼承的,上面也會怎麼繼承。

這邊就是 class 層級的 object model.

*

剩下 meta-class 層級的部份,欲知詳情,下回分曉。
因為我寫不下去了,腦袋一片混亂...

3 retries:

山邊美溪 said...

東方音樂我手上只有夢違科学世紀。想要再找其他的。你那邊有嗎?我比較想要紅魔館、風神錄的音樂。

godfat 真常 said...

沒有 OST 喔,ZUN 只有出一些 collection.

大空魔術
http://d-stage.com/shop/detail.php?seq=3641

卯酉東海道
http://d-stage.com/shop/detail.php?seq=3638

蓮台野夜行
http://d-stage.com/shop/detail.php?seq=3634

蓬莱人形
http://d-stage.com/shop/detail.php?seq=3632

godfat 真常 said...

最近好像有重出,所以應該都買得到 @@
本來漲價漲到很誇張說

Post a Comment

All texts are licensed under CC Attribution 3.0