Continuation Confusion

B

Blaine Buxton

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
 
P

Pit Capitain

Blaine said:
But, I still think the method's local state should be saved on the
stack as well. Am I missing something?

Hi Blaine,

if you look at this small example, you see that local variables are
indeed *not* saved by continuations:

v = 1
c = callcc { |cc| cc }
puts( v, c )
if Continuation === c
v = 2
c.call( 5 )
end

Output:

1
#<Continuation:0x2a6b738>
2
5

Feel free to ask if you need more help.

Regards,
Pit
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top