Continuation in ruby


#1

Hi all.

I’ve written the following code to learn continuations in ruby only to
fail. Please have a look at:

def print_num
for i in (1…10)
puts i
if i % 2 == 0; callcc{|c| return c}; end
end
end

cont = print_num
puts “Yae, I love even~”
cont.call
puts “Bye”

This code produces:

C:\WINDOWS\system32\cmd.exe /c ruby a.rb
1
2
Yae, I love even~
3
4
Yae, I love even~
5
6
Yae, I love even~
7
8
Yae, I love even~
9
10
Yae, I love even~
Yae, I love even~
a.rb:10: undefined method `call’ for 1…10:Range (NoMethodError)
shell returned 1
Hit any key to close this window…

This is contrary to my intuition. I’ve called cont.call only once, and
cont.call should put the following command, put “bye”, into stack. I
can’t figure out the reason why cont.call is called indefinitely.

Best,
Minkoo S.


#2

On 2/14/06, Minkoo S. removed_email_address@domain.invalid wrote:

Hi all.

I’ve written the following code to learn continuations in ruby only to
fail. Please have a look at:

From another learner
Look at my following try
def print_num
for i in (1…10)
puts i
if i % 2 == 0; callcc{|c| return c}; end
puts “** cont.call brings you here”
end
return nil
end

cont = print_num
puts “Yae, I love even~”
cont.call if cont
puts “Bye”

Hope this helps
Prasad


#3

Minkoo,

When you call cont.call, the control goes right back to the end of
callcc block with all the context in tact. So your program’s control
flow looks like this:

  1. cont = print_num # calls print_num method
  2. callcc {|c| return c} # at i % 2 == 0, print_num returns with the
    continuation as a return value, which is now assigned to cont
  3. puts “Yae…”
  4. cont.call # now the control goes back to “}” of callcc with the
    variable i == 2
  5. for loop continues
  6. go to step 2 unless i == 10
  7. at i == 10, callcc block returns one final time
  8. puts …
  9. cont.call
  10. now that i == 10 for loop finishes and the return value of
    print_num at this time is (1…10), because “for loop” is essentially
    (1…10).each {|i|} in disguise, and #each returns self
  11. puts …
  12. cont.call # argh! this time you’re calling (1…10).call
  13. NoMethodError exception

This is what has happened.

Hope this helps.

Jesse


#4

Now I get it.

So the continuation returned from print_num by cont = print_num
contains not only the context within print_num method, but also the
context of “cont = print_num”. In other words, cont contains (1)
print_num was called, (2) location within print_num, (3) and variables
in its stack.

Thank you, folks.

Best,
Minkoo S.