Patrick Roemer
2/3/2009 1:46:00 AM
Responding to Paul w Florczykowski:
[Disclaimer: I'm certainly not a pro on continuations, but I'll just
give it a try. Please bear with me.]
> def loller(id, num, that)
> loop do
> puts id.to_s + " " + num.to_s
> num += 1
> sleep(0.5)
>
> # why do i need to update 'that' here, but not 'well' in the while loop??
> # callcc { |here| that.call(here) }, w/o assignment doesn't work here
> that = callcc { |here| that.call(here) }
>
> # any subsequent calls to 'well' (well.call) should return to THIS POINT
> # with num == 35
> # since I never reassign the continuation referenced by 'well'
> end
> end
>
> i = 0
> well = callcc { |c| loller(1,34,c) } #A
>
> while true
> # why don't I need: well = callcc { |here| well.call(here) }
> # callcc { |here| well.call(here) }, w/o assignment works here!!!
> callcc { |here| well.call(here) } #B
> puts "back to root " + i.to_s
> i += 1
> end
Continuations don't capture a frozen state but rather a live environment
- you can return to the same continuation and encounter different local
state each time.
i = 0
callcc{|cc| puts "assign once"; $cc = cc}
i += 1
puts(i)
$cc.call unless i == 3
So you don't need to 'update' your continuation references in order to
keep track of changed state (such as the num value inside loller). The
reason you require the assignment to 'that' is because on the initial
method invocation it will have the 'wrong' value - it will transfer back
to #A, and you have to fix that after the first control transfer back
into loller via 'well' to point to #B instead. (Which is also why you
get two successive messages from loller before the root messages kick in.)
A slightly modified version of your code:
def loller(id, num, that)
loop do
puts id.to_s + " " + num.to_s
num += 1
sleep(0.5)
callcc { |here| that.call(here) }
end
end
i = 0
well = nil
while true
if(well.nil?)
well = callcc { |there| loller(1,34,there) }
else
callcc { |there| well.call(there) }
end
puts "back to root " + i.to_s
i += 1
end
Best regards,
Patrick