作者giive (lala)
看板Ruby
标题[心得] Ruby 的 '延续' 物件 : Continuation
时间Wed Sep 13 14:29:25 2006
因为我不会用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)