Why does Ruby have callcc?

Ok, and the reason you need to have this lambda is that callcc is a
function that takes one argument: a function which itself takes one
argument, the CC. Because my-fun requries more than one argument,
you need the lambda, right?

Correct. You need to wrap it in an anonymous function to pass along the arguments.

So it looks like Ruby is trying to look like the scheme implementation.
Sometimes trying to mimic the way things look in a functional language
when programming in an imperative language makes for convoluted code.
There may be some subtlety I’m missing, but it seems like you aught to
be able to have a “returncc” function in scheme that takes no arguments
and returns a continuation context thingo, then use it like:

(my_fun (returncc) arg1 arg2 arg3 …)

It could probably even be implemented as

(lambda (cc) cc)

Though, my scheme is weak to nonexistent so I’m not 100% sure I
have the syntax right.

I’m just not sure exactly where things end up if you call that
continuation context… though I suppose you’d just end up right in the
middle of assigning arguments to a method call, followed by
actually calling the method.

If that’s possible, this should work in Ruby:

my_fun(Continuation.new, arg1, arg2, arg3, …)

Or, more clear to me:

cc = Continuation.new
my_fun(cc, arg1, arg2, arg3, …)

Am I out to lunch, or does any of this make sense?

Ben

Well, as people have said, continuations are really related to function calls, so in essence, if you do:

cc = Continuation.new

cc.call(blah)

Then after that point, cc would contain blah, since calling a continuation returns from the call that created the continuation. That’s why you can’t just do:

cc = callcc { |cc| cc }

Which is essentially equivalent to your Continuation.new. To keep cc valid, you need to do something like:

cc, else = callcc { |cc| cc, nil }

cc.call(cc, return_stuff)

Now, you could eliminate the need for passing a block and being able to call functions directly, like:

val = callcc(method(:func), arg1, arg2, …)

Because in Ruby callcc could do:

def callcc(func, *args)
# create continuation somehow
func[cc, *args]
end

Which automatically passes extra arguments along. However, given that you can’t pass methods in a first-class manner without an explicit call to method(), this looks a little ugly to me.

I suppose you could make continuations with a Continuation.new semantic, but you’d lose some of the functionality of callcc unless you wrote it yourself. Otherwise continuations would be like labels and goto that have the added ability to jump between functions.

I hope this has made some sense. I’m no expert in continuations by any means.

  • Dan

P.S.: If you wanted to implement the callcc for functions directly, you can do it easily with the current callcc:

def func_callcc(func, *args)
callcc { |cc|
func[cc, *args]
}
end

Likewise, you might be able to implement your continuation paradigm like so (I think):

class MyContinuation
def initialize
callcc { |@cc| }
end

def call(*args)
    @cc.call(*args)
end

end

(Note: I haven’t tested this, and won’t be able to until this evening)

I think doing:

mcc = MyContinuation.new

mcc.call

Goes back to the line “mcc = MyContinuation.new” Note that any arguments to mcc.call will effectively be ignored, because it’s a constructor (I think). This means that if you used this paradigm for all continuations, returning something with a cc.call would require Continuation.new to create a continuation of the call to the enclosing function, instead of a continuation of the constructor (or something like that), which may or may not be possible, since I don’t know how Ruby implements continuations (it would probably require Ruby using CPS, which is of debatable value). But, this post script has gone on far too long.