From: dolio@... (Dan Doel) Date: 2003-07-22T15:29:19+09:00 Subject: callcc and insomnia 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.