[rbx ] include_remove

看板Ruby作者 (godfat 真常)時間16年前 (2008/11/02 01:45), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/4 (看更多)
我想應該大部份 ruby 玩得稍微深入一點的人,都會覺得需要 uninclude 吧? 像是之前在 ruby-talk 看到挺瘋狂的 namespace 概念,就需要這種功能。 而一般在 ruby 裡想幹種種事,會被建議這樣用: BackupUser = User User = BackupUser.dup User.include Something # ... # ... # 拋棄 Something 吧 User = BackupUser.dup 我個人是覺得這是個很爛的招式 XD 有人用 C 寫 extension 真的做到了 uninclude: http://github.com/yrashk/rbmodexcl/tree/master 一點討論在這: Any reason for having no module exclusion functionality in Ruby http://www.ruby-forum.com/topic/150696 觀察了一下他在 rubinius (rbx) 上的實作,發現其實很單純: http://github.com/yrashk/rbmodexcl/tree/master/rbxmodexcl.rb 不過程式有點醜,所以我改了一下... http://github.com/godfat/rbx-include_remove/tree/master/include_remove.rb 基本上真的很單純,大概架構就是 module 本身是一個一個串起來的, 由 Module#superclass_chain 可以看出來。被 include 進去的 module, 會變成 IncludedModule 存在 superclass_chain 中。 而這個 chain 則是由類似 linked list 串起來的,由 superclass 串起。 藉由 Module#superclass= 即可改寫這個 linked list, 藉此移除 included module. 這邊比較神秘的是,superclass 本身是忽略 IncludedModule 的, 我想這是為了相容 MRI 的關係。所以查詢包含 IncludedModule 要用 direct_superclass. 其實 rubinius 類似這樣的動作還滿多的, 關於相容方面,JRuby 做得比較徹底。但 rubinius 彈性大到不可思議... 總之就是把 superclass_chain 當 linked list, 找到目標後移除目標 module, 像是這樣: prev.superclass = next.superclass 而 extend_remove 就利用前面寫好的 include_remove 即可, 因為 extend 其實就是 metaclass 的 include... metaclass.include_remove(mod) 這樣寫就好了。 == 比較神勇的是,rubinius 幾乎什麼都可以改寫,我甚至可以改寫 if condition then_clause else else_clause end 產生出來的 bytecode... 剛剛試了一陣子,要改寫 bytecode 的行為大概就不行了 本來想改寫 :goto_if_false 和 :goto_if_true, 但這好像是 c++ 的部份... 裡面還用到 reinterpret_cast 和 bitwise and, 不是很確定是什麼意思... 我想應該還有其他方法可以改寫 if 的行為才對,可能要改寫輸出的 bytecode. 把 if 再 wrap 一層,在外層呼叫 .nil? 不過雖然 rubinius 擴充性真的強到不可思議,跑起來也真的是好慢... 改寫 lib 後重新 compile 都要等好幾秒,啟動也要好幾秒... -- By Gamers, For Gamers - from the past Interplay -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.135.28.18
文章代碼(AID): #1939N2CG (Ruby)
文章代碼(AID): #1939N2CG (Ruby)