From: Blaine Buxton Date: 2005-05-01T03:58:09+09:00 Subject: Continuation Confusion Hello, I was playing around with continuations by studying the generator code in Hal Fulton's Ruby Way book. I decided to re-implement the code to test my understanding. I decided to add the ability to backup the generator and started to get "weird" results. I started to pass the intermediate values on the stack and everything works. But, I would like to understand better why. Can anyone help me? Thanks in advance! Here's my code with comments and tests: #playing with continuations #inspired by Generator code in Hal Fulton's book #I read it and then tried to recreate it to test my understanding #I add the ability to "backup" the generator. I've added tests as well. # #I have to pass the locals on the stack to get it to work correctly? Why is this? #Is there something I am missing? I did use one less continuation, but it's #just the continuation to continue the loop of the generator. require 'test/unit' class Generator attr_accessor :currentContext, :contextHistory def initialize() self.currentContext=nil self.reset end def next callcc do |here| self.currentContext=here if self.contextHistory.empty? generatorLoop else self.contextHistory.last.call end end end def backup self.contextHistory.pop end def answer(value, *args) callcc do |cont| self.contextHistory.push(cont) self.currentContext.call(value) end args end def reset() self.contextHistory=[] end end class Fibonacci < Generator def generatorLoop previous, current=0,1 loop do #I pass the previous and current local variables as arguments just so they are returned #If I don't pass them, weird things happen which makes me think Ruby #continuations only save part of the state or treats closures special on the #stack. The variables are local to the method and not the closure. But, I still #think the method's local state should be saved on the stack as well. Am I missing #something? #works previous, current = answer(current, previous, current) #doesn't work, but I think it should, what am I missing? #answer(current) previous, current = current, previous + current end end end class TestFibonacci < Test::Unit::TestCase attr_accessor :to_test def setup self.to_test=Fibonacci.new end def teardown self.to_test=nil end def test_next assert_equal(1, self.to_test.next) assert_equal(1, self.to_test.next) assert_equal(2, self.to_test.next) assert_equal(3, self.to_test.next) assert_equal(5, self.to_test.next) assert_equal(8, self.to_test.next) end def test_back (1..6).each { self.to_test.next } assert_equal(13, self.to_test.next) self.to_test.backup assert_equal(13, self.to_test.next) self.to_test.backup self.to_test.backup assert_equal(8, self.to_test.next) assert_equal(13, self.to_test.next) assert_equal(21, self.to_test.next) end end -- Blaine Buxton, Mad Scientist In Training My Amps: Smalltalk, Lisp, and Ruby http://www.blainebuxton.com _________________________________________________________________ Is your PC infected? Get a FREE online computer virus scan from McAfee� Security. http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963