[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Continuations

Paul w Florczykowski

2/2/2009 10:11:00 PM

Please help. I'm totally confused by following behaviour with regard to
continuations (Ruby 1.8.7) My goal was to simply jump between two loops,
which worked fine. But I do not really understand this behaviour:


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) }

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) }
puts "back to root " + i.to_s
i += 1

end



This program increases a simple counter in each loop, and prints it.
However, I do not understand why this works, since I am not reassigning
the continuation returned by the loop in function "loller". The call
made from the while-loop was looking like this to begin with:

well = callcc { |here| well.call(here) }

Which gives the same result, even when i remove the assignment. That
means the 'well' variable still references the original continuation
i.e. value of 'num' inside loller should always be the same as in
original continuation? Should I remove the analogous assignment from the
loop in "loller" then as expected i never get "back to root" printout,
since then "loller" always returns to the point after the original
assignment, and thst is just before the while loop.

Anybody who understand this, please explain. Big thanks in advance.

/Paul W Florczykowski
--
Posted via http://www.ruby-....

3 Answers

Patrick Roemer

2/3/2009 1:46:00 AM

0

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

Brian Candler

2/3/2009 11:37:00 AM

0

Paul w Florczykowski wrote:
> Anybody who understand this, please explain. Big thanks in advance.

The way I think of it: firstly

* A closure is an environment in which variables are evaluated and
stored

Once you 'get' closures, then:

* A continuation is a closure plus an execution pointer

Some closure examples I read a while back were not helpful. One I think
talked about going across a railway crossing, getting run over by a
train, and then rewinding to before you went across.

Using a continuation, you can rewind to before you went across, but
you'll still be dead :-)

Regards,

Brian.
--
Posted via http://www.ruby-....

Paul w Florczykowski

2/3/2009 6:04:00 PM

0

Patrick Roemer wrote:
> ...
> 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.)
> ...
> Best regards,
> Patrick

Appreciate the reply! it actually helped me understand this! Thanks
again!
--
Posted via http://www.ruby-....