From: Mikael Brockman Date: 2004-08-21T08:26:47+09:00 Subject: Re: ruby, actors, continuations, Kernel#callcc Mikael Brockman writes: > zuzu writes: > > but i still can't quite seem to grok continuations, at least in terms > > of interpreting it for ruby, w/r/t closures and Kernel#callcc. > > For me, there wasn't really an a-ha moment, at which point I immediately > grasped the implications of CALL/CC. Rather, I kept playing around with > it, and after I while I just found myself understanding. > > Nevertheless, if you want more stuff to read, you can try > http://mikael.phubuh.org/Media/Writing/Continuations/. I'm not much of > an educator, but at least it uses Ruby. By the way, that code uses a lot of catch/throw, which is a typical use of continuations in languages that lack exception systems (i.e., Scheme). Maybe this implementation will help you understand what's going on: | class Catcher | def initialize | @futures = {} | end | | def catch (id) | callcc do |future| | @futures[id] = future | yield | end | end | | def throw (id) | @futures[id].call | end | end | | $global_catcher = Catcher.new | | def my_catch (id, &block) | $global_catcher.catch id, &block | end | | def my_throw (id) | $global_catcher.throw id | end You can use it just like regular catch/throw, I think: | > my_catch :foo do | > puts "hello" | > throw :foo | > puts "world" | > end | hello | => nil An interesting bug/feature is that it neglects to remove the continuations after the block is done, so you can make an obfuscated infinite loop like this: | my_catch :foo do | puts "foo" | end | puts "bar" | throw :foo It'll print foo followed by an infinite amount of bars. So in fact, the Catcher class actually implements something like a Common Lisp TAGBODY or a C tag/goto thing, except you can't go to labels that you haven't declared yet. mikael