Hello,
This summer I’ve been delving a lot more into various programming
languages that I had previously wanted to learn but didn’t really have
time. So, I’ve been studying my Ruby, Scheme, Smalltalk and Haskell
lately, reading a lot of newsgroups and such. So, of course, I came
across the idea of closures, continuations and coroutines
(specifically reading the parrot blog) and became intrigued by them. I
hadn’t heard of them previously being that I came from C/C++ and Java
mostly. I wanted to implement coroutines (Perl 6 style, as described
in the blog**) myself since most languages don’t have those. I tried
in Scheme first but became very confused as the syntax is very foreign
to me still, so I decided to switch to Ruby (which I like better
anyhow) before I tried again in Scheme.
And, I’ll add, that I succeeded, as this code shows:
class Coroutine
def initialize(method)
@body = method
end
def call(*args)
callcc do |@jump_out|
if @jump_in.nil?
ret = @body.call(*args) do | val |
callcc do | @jump_in |
@jump_out.call val
end
end
@jump_in = nil
@jump_out.call ret
else
@jump_in.call
end
end
end
end
Which lets you write code like this:
def func(a, b, c)
yield a
yield b
c
end
cot = Coroutine.new method(:func)
puts cot.call(“mook”, “mock”, “morn”) # => mook
puts cot.call(“mush”, “milf”, “maern”) # => mock
puts cot.call(“mush”, “milf”, “maern”) # => morn
puts cot.call(“mush”, “milf”, “maern”) # => mush
puts cot.call(“mush”, “milf”, “maern”) # => milf
puts cot.call(“mook”, “mock”, “morn”) # => maern
Which I was pleased with.
Now for my question:
When I first wrote it, intstead of:
ret = @body.call ...
...
end
@jump_in = nil
@jump_out.call ret
I simply let @body.call return which should (I thought) return from
the callcc with an appropriate value. This meant that each time I had
to do something that looked like:
loc, @jump_in = @jump_in, nil
loc.call
so that I didn’t get in an infinite loop.
However, the output for 3 calls would be as follows:
val1
val2
val3
val1
val2
So func got called extra times.
So, maybe some of the gurus out there can help me out and tell me
what’s different about the code that works and the code that I thought
was semantically the same but doesn’t work in practice. I’ve gone
through the flow in my mind over and over but I can’t figure it out,
at least not this late.
Thanks for any help
Dan
** P.S.: By Perl 6 style coroutines, I mean routines that look as
follows (I may have syntax wrong as I don’t really know perl well)
sub foo is coroutine {
yield "a"
yield "b"
yield “c”
}
Where each “yield” is effectively a return with support for resuming
afterwards. All coroutine implementations I’ve seen (Scheme or Ruby,
that is) aren’t like this at all. They’re more like co-operative
threads that can switch context amongst one another, instead of
functions that can return and resume (as the parrot blog suggests). Is
the definition in the blog not the standard definition of coroutines?
From what I’ve read, what I’ve made seems more like a Python
generator. Is a generator a special case of a coroutine? Or is it the
other way around? Or maybe they’re the same or totally unrelated?
Maybe I’m just confused. 
Sorry for the extremely long post.