[心得] Ruby 的 '延續' 物件 : Continuation

看板Ruby作者 (lala)時間18年前 (2006/09/13 14:28), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/2 (看更多)
因為我不會用ASCII 所以要看比較清楚,有顏色的解說就看我的 Blog 吧 http://lightyror.blogspot.com/2006/09/ruby-continuation.html 試著想想這個程式(出自 Beyound JAVA 範例) 1 def con_loop 2 for i in 1..5 do 3 puts i 4 callcc { |a| return a } if i == 2 5 puts '#' 6 end 7 return nil 8 end 9 puts 'Before loop call' 10 cont = con_loop() 11 puts 'After loop call' 12 cont.call if cont 13 puts 'After continuation call' 想想這個程式會怎麼做? 這是這個程式的結果,很出人意料之外吧 Before loop call 1 # 2 After loop call # 3 # 4 # 5 # After loop call After continuation call 為什麼 After loop call 執行了兩次? 為什麼 1 2 跟 3 4 5 中間夾了一個 After Call 這就講到一個有趣的物件 Continuation 他是一個物件,裡面記載著程式運作的狀態 好像遊戲打到一半,媽媽叫你去吃飯,你只好心不甘情不願的去存檔 可是吃完飯,load 剛剛存的檔,你的角色的經驗值都還在,寶物都不會不見一樣 Continuation 就是那個遊戲的紀錄檔 現在可以討論這個程式了 i 進入loop裡面 ,puts 1 ,puts 2 當 i = 2 時 下一行也就是第四行,因為 if i == 2 這個敘述的緣故( 媽媽叫你吃飯了) 會被強迫跳出這個 loop ( return a ) (只好關機) 但是, callcc { |a| return a } 他會 return 一個 continuation 物件 continuation 裡面的內容就是你遊戲的紀錄檔 他會在 10行裡面,存到 cont 這個 Object 裡面 (存檔等下再來玩) 所以程式會 puts 1 , 2 之後,就進入第11行的 puts 'After loop call' 這也是第一次的 After loop call 印好 After loop call 第12行,他會檢查 cont 這個物件有沒有值 (檢查存檔在不在) 發現到有值,就執行 Continuation 物件的 call method (呼叫存檔) 他會到 loop function 裡面 ,剛剛 return continuation 物件的地方 最重要的是 他會紀錄 i 這個 tmp variable 是 2,因為他本來就會紀錄程式狀態 然後執行第五行的 puts '#' 這也是為啥,結果裡面第一個 After loop call 後面是 # 再來他會繼續的進行 loop ,從 i =3 ~ 5 最後執行結束,他會在第7行 return null 值,交給 cont 物件 之後他就會執行第二次的 After loop call 這個機制怎麼玩呢? 我們可以想到,程式執行到一半,有個 interrupt 他出去執行一下 error handler ,然後回來繼續處理剛剛的事情 當然我們當然可以用其他方式做到類似的事情,不過這個作法的確提供很方便的方式 根據 Wikipedia 的講法 Lisp ,Ruby ,Smalltalk 都有提供類似的作法(果然 Ruby 是 Perl + SmallTalk + Lisp ) 但是我比較好奇 C 也有這種作法? * C: setcontext et al. (UNIX System V and GNU libc) 下一篇我會提到利用這個觀念,產生的延續性伺服器的想法 -- lighty RoR 是一個介紹 lighttpd , SQLite , Ruby and Rails 的 Blog http://lightyror.blogspot.com/ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.218.90.242 ※ 編輯: giive 來自: 61.218.90.242 (09/13 14:30)
文章代碼(AID): #151wJxy0 (Ruby)
文章代碼(AID): #151wJxy0 (Ruby)