Ruby 板


LINE

※ 引述《godfat (godfat 真常)》之銘言: : 簡單地說,當我們說:「unit.walk_to(dist)」時,是否可以獲得 unit 的真實 : 型別?那麼,何不故技重施,以便獲得第二個真實型別? : 避免寫太長不好閱讀,待續… 原本的程式碼是 C++ 的,這裡我以 Ruby 做示範: class A def go rhs rhs.goA self # 知道左邊是 A 了!右邊是誰? # 倒轉過來呼叫就知道右邊是誰了 end def goA rhs # 上面假設 rhs 也是 A, 那麼倒轉呼叫後就會到此 # 於是我們知道,左右都是 A puts 'AA' end def goB rhs; puts 'BA'; end def goC rhs; puts 'CA'; end end class B def go rhs; rhs.goB self; end def goA rhs; puts 'AB'; end def goB rhs; puts 'BB'; end def goC rhs; puts 'CB'; end end class C def go rhs; rhs.goC self; end def goA rhs; puts 'AC'; end def goB rhs; puts 'BC'; end def goC rhs; puts 'CC'; end end a, b, c = A.new, B.new, C.new a.go b # AB b.go c # BC c.go a # CA a.go c # AC 不過其實缺點還滿多的,一、程式寫法不是那麼地直覺 二、呼叫順序變得很重要,難以將 a.go b 和 b.go a 變成等價 三、如果要支援更多的 invoker, 會變得很困難且繁瑣 summary multi-method/dispatch 的三種實作法 1. 暴力搜尋 缺:1. error-prone 2. 難以支援二種以上的型別 優:1. 執行效率良好 2. 實作方式簡單 2. 先註冊,後用 map/hash 搜尋 (Ruby lib multi 的實作法) 缺:1. 需要額外資源 2. 執行效率差 優:1. 彈性佳、容易擴充至支援任意多種型別 2. 操作方式簡單 3. 翻轉搜尋 缺:1. 彈性非常差 2. 難以支援二種以上的型別 優:1. 執行效率良好 2. 操作方式簡單 個人覺得,第一種做法最直覺,第二種做法最好,第三種做法最有趣 XD 三種方法都大致看完後,就來看 http://rubyforge.org/projects/multi/ 用起來感覺如何了 (p.s. 據說 Common Lisp Object System 直接支援 multi-method/dispatch) 先來看範例,取自裡面的 multi_example.rb require 'pp' require 'multi' require 'smulti' # btw, 順便問一下 XD 為何如果我不先 require 'rubygems' 的話, # multi 等用 gem 安裝的 lib 會讀不到啊?rubygems 的設定翻半天, # 還是搞不清楚是怎麼回事|||b class Foo def initialize multi(:hiya, 0) {|x| puts "Zero: #{x}" } multi(:hiya, Integer) {|x| puts "Int: #{x}" } multi(:hiya, String) {|x| puts "Str: #{x}" } multi(:hiya, lambda {|x| x.size > 2 }) {|x| puts "GT2: #{x}"} end end f = Foo.new() f.hiya(0) # Zero: 0 f.hiya(5) # Int: 5 f.hiya("hello") # Str: hello f.hiya([1, 2, 3]) # GT2: 123 begin f.hiya([1]) rescue puts $! # No match for #<Foo:0x7fec852c>.hiya([1]) end multi(:fac, 0) { 1 } multi(:fac, Integer) {|x| x * fac(x-1)} puts fac(5) # 120 multi(:reverse, []) { [] } multi(:reverse, Array) {|list| [list.pop] + reverse(list) } pp reverse([1,2,3]) # [3, 2, 1] multi(:baz, 3, Object) { puts 3 } multi(:baz, Object, String) {|o, str| puts str } baz(3, "three") # 3 baz(2, "two") # two multi(:retest, /^a(.*)/) {|x| x } multi(:retest, String) { '' } pp retest('foo') # "" pp retest('afoo') # "afoo" smulti(:foo, 'a') { puts "a FOUND" } smulti(:foo, /./) {|s, rest| foo(rest) } smulti(:foo, // ) { puts "a NOT FOUND" } foo('a') # a FOUND foo('') # a NOT FOUND foo('ab') # a FOUND foo('ba') # a FOUND foo('bb') # a NOT FOUND # 以下是我額外的測試,結果和上面的 a FOUND 系列完全相同 multi(:boo, /.*a+.*/) { puts 'a FOUND' } multi(:boo, String) { puts 'a NOT FOUND' } boo('a') boo('') boo('ab') boo('ba') boo('bb') 也就是說,這個 multi 其實該有的都有了,甚至 class 和 instance 可以 混著使用。另外需要注意的是越先定義的 method 有越高的優先權, 如果寫 multi(:coo, Integer){} multi(:coo, 0){} 則下面的 method 永遠不會被 invoke, 因為 0 屬於 Integer... 這種時候,0 一定要優先定義 我個人認為這也許算是個缺點,有空會看看能不能修正這個問題 另外還有一個我覺得很大的問題是:當引數完全符合,但有多餘參數剩下時, 仍然算是 match, 參照以下: multi(:test, Integer, String, Integer){puts 'match'} test(1, 'XD') 1 符合 Integer, 'XD' 符合 String, 欠 Integer, 但依然算是 match 我不知道作者是不是故意這樣做的,還是單純只是一個 bug 除此之外,其實還欠缺對稱性的問題,如 a.go b 和 b.go a 是否相同? 為此,我對該 lib 稍作了一點暫時性的擴充,使得: multi_unordered(:combine, A, B){ puts 'AB' } a, b = A.new, B.new combine(b, a) # AB combine(a, b) # AB 欲知詳情,請待下回分曉 -- 「行け!Loki!」(rocky ロッキー) -Gurumin ぐるみん 王子? XD --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.217.103.191
1F:→ godfat:太累了,接下來的改天再寫... 12/22 00:02
2F:→ yjc1:因為 rubygems 會 override require , 等同 require_gem 12/22 15:35







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:e-shopping站內搜尋

TOP