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灯, 水草

请输入看板名称,例如:BuyTogether站内搜寻

TOP