Continuations with Ruby
I have been diving into continuations a bit lately and would like to share with you some of my findings. First of all, allow us to let the code speak for itself for a moment. Fire up irb and copy the following in:
class Foo
def bar
catch :break do
puts "starting..."
callcc do |@continuation|
puts "pausing..."
throw :break
end
puts "finished"
end
end
def continue
@continuation.call
puts "this puts will not ever be executed"
end
end
f = Foo.new
f.bar
# => starting...
# => pausing...
f.continue
# => finished
You will notice a few things about this code. First is that callcc
takes a parameter but does not use it. Rather, that parameter
actually becomes a block in it of itself which is called in the
continue method. Next is that within the callcc block we catch a
symbol. We do this specifically and only with the intent of stopping
the flow of the code. The final thing to notice is that as soon as you call the @continuation block, it sends you right back into the bar method to the point after the callcc block is made and continues along its merry way... it does not hop back over to the continue method when finished... it actually transfers into a whole new scope.
If this is new to you, chew on it for a while and enjoy. If this is
old hat, then I have more continuations cooking for you soon. To give
you a hint, there are plenty of ActiveRecord plugins out there but I
am thinking of building on of the first ActionController plugins. I
call it acts_as_continuation.
Technoblog reader special: $10 off web hosting by FatCow!
2 Comments:
Instead of abusing exceptions, why not use throw/catch? Unlike exceptions, throw/catch is actually intended to be a control-flow tool, and is very useful in conjunction with callcc.
8:15 AM, June 09, 2006
You are correct, I have updated the example to reflect this.
9:00 AM, June 09, 2006