Ruby 板


LINE

Ruby standard library 裡有個 Generator, 放在 generator.rb 裡。 大抵上是拿來把 internal iterator 轉換成 external iterator 用的。 兩種 iterator 有什麼差別?如果你熟悉 C++ 或 Java 的話, 他們所使用的就是 external iterator. 顧名思義,這是一種外部的 iterator, 即 iterator 本身跟 container/collection 是分開的。 C++: typedef std::vector<int> vint; vint v; for(vint::iterator i=v.begin(), iend=v.end(); i!=iend; ++i) std::cout << *i << "\n"; Java: Vector<Integer> v = new Vector<Integer>(); for(Iterator i=v.iterator(); i.hasNext();) out.println(i.next()); 如果是 internal iterator 的話,就像是 foreach/for in 那樣 C++: BOOST_FOREACH(int i, v){ // 由於這是 macro 做的,不確定能不能省略 std::cout << i << "\n"; } Java: for(int i: v) out.println(i); 也就是說,你只能依序得到元素,但你不能操控會給你的元素是什麼。 external iterator 有比較強大的彈性,internal iterator 使用起來方便。 Ruby 的 each 很明顯是 internal iterator, 你把要施行的動作傳給 container/collection, 然後由他來替你施行動作。 可以看成是這樣: def each func = nil, &block # 以下決定使用 block 或傳入的 Proc like 物件,寫入 func 中 if block_given? func = block else raise TypeError, "#{func} don't respond to :call" unless func.respond_to? :call func = func end # 以下依次呼叫外部 Proc like 物件,傳入被 travel 者 0...self.size.times{|i| func.call self[i] } end 由於 travel 的動作被隱藏起來了,所以使用時方便,不用再去說明 travel 法。 缺點也正是因為 travel 被隱藏起來了,所以如果不是要用預設的 travel 法, 則動他不得。要用非預設的方式,只能使用 external iterator. Ruby 目前沒什麼好的 external iterator, 所以只好使用 Generator 去模擬。 (當然,Array 很好做 external iterator, 但其他的就比較困難。) 用法大概是像這樣: v = [0, 1, 2, 3, 4] g = Generator.new v while g.next? puts g.next end Generator 的做法很單純,他還是使用 each 去呼叫,不過卻去「卡住」 travel 的過程。這就是靠 Continuation 去做了。 關於 Continuation, 本板前面有其相關心得,不多重複了。 寫成概念有點像這樣: def next @target.each{|i| 卡住 return i } end 每次呼叫 Generator 的 next 時,就放掉「卡住」,於是傳回當時的 i, 然後在傳回下一個 i 之前,再卡住執行流程。next 可以用這種概念實作出來。 不過 prev 就沒辦法了。Generator 有提供 rewind, 使 travel 整個重來, 但是沒有 prev 這種能夠往前走一格的方式…。要有的話,勢必不能使用 each. 幸運的是……由於 standard library 的 generator.rb 我看不懂, 看了好一陣子,只得到了點概念,但還是搞不懂他為什麼要把實作變得 這麼複雜 :( 沒記錯的話,總共有三個 Continuation 物件,又有一個額外的 queue array... 我完全搞不懂他這個 queue 存在的意義。 所以我自己嘗試寫了一下,以確保我沒有誤解什麼東西。我只用了兩個 Continuation, 沒有 queue. 當然,整個概念還是從他的程式碼來的, 我只是把我看不懂的部份拿掉,然後用自己的意思解讀一次。 用該檔案裡面的 unit test 測試了一下,每一個測試都通過了, 很搞不懂原本的實作為什麼要弄得這麼複雜…。更何況由於我撰寫的 裡面少了一個 Continuation 和一個 array, 執行效率應該還比較高。 不知道是不是我疏忽了什麼,不然這樣的狀況似乎有點詭異。 * 原本我是想詳細解說我的實作的,不過 Continuation 我覺得有點複雜, 從寫完到現在也經過一段時間了,詳細的做法我已經不記得了…。 Orz 更何況此篇已經有點太長了,也差不多是「欲知詳情,請待下回分曉」的時候 XD 所以以下就僅附上程式碼,以 Ruby license 釋出。 p.s. 我覺得 Continuation 太過於複雜(另類 goto),似乎應該少用為妙 class Generator include Enumerable def initialize enum = nil, &block if enum @block = lambda{|g| enum.each{|i| g.yield i}} else @block = block end @index = 0 @value = nil if @con_next = callcc{|c|c} @block.call self @con_next.call end end def next raise EOFError, "no more elements available" if end? @index += 1 result = @value @con_yield.call if @con_next = callcc{|c|c} result end def yield value @value = value @con_next.call if @con_yield = callcc{|c|c} end def next? return true if @con_yield return false end def end? !next? end def index @index end alias_method :pos, :index def current raise EOFError, "no more elements available" unless @value @value end def rewind initialize &@block self end def each rewind yield(self.next) while self.next? self end end -- In Lisp, you don't just write your program down toward the language, you also build the language up toward your program. 《Programming Bottom-Up》- Paul Graham 1993 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.28.18
1F:推 poga:好文我推 03/01 22:37







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

請輸入看板名稱,例如:Tech_Job站內搜尋

TOP