I have been interested in these continuation-thingys for a while now, so now
that the subject came up, I decided to take a good look.
I now think I understand how they work, and when they might be used, but that
still leaves a few questions:
- Why do they have the strange syntax they have
- Why don’t they have more “meat” to them?
I found a bunch of websites all talking about continuations:
http://www.ai.mit.edu/~gregs/ll1-discuss-archive-html/threads.html#01372
http://www.ps.uni-sb.de/~duchier/python/continuations.html
…
The summary is that Continuations are essentially “goto with parameters”, or
even more simply, like setjmp, longjmp.
To do continuations, you need to save the state of the VM at the “site of the
continuation”, and then be able to load that up when asked to do so. Given
that, I am puzzled by the syntax they have in Ruby. First of all, why the
block? In most of the examples I’ve seen, there doesn’t seem to be a good
reason to have a block. The only reason the block is necessary seems to be
that the end of the block marks the location where Continuation#call will go
to. Also, why are they created by Kernel.callcc? Why not Continuation.new,
where the location from which to continue when the Continuation is called is
the next expression after .new.
The second issue is why Continuations have nothing but a .call method.
Because they should encapsulate things like stack and program-counter values
at the time of the call, it would seem to me like these are useful things to
have available.
Say, for instance, that Continuation had a “stack” accessor, it could return
something similar to Kernel.caller(). Continuation could also have a
"program_counter" attr_reader that would return some sort of binding object
(or a symbol or something) that would represent the location in the program
that would be jumped-to by .call. I think it would be interesting to be able
to manipulate Continuations in more ways than just .calling them. Maybe keep
an array of them around and jump to the one with the smallest stack? I don’t
know.
While I’m busy redesigning the language, what if Kernel.caller could return an
array of Continuation objects, any of which could be .called? If I
understand things correctly calling a continuation is essentially no
different from returning from a method call. The PC is set to a certain
address, the stack is unwound one level, and the only difference is that a
certain value is held somewhere (in a register?)
Anyhow, before today I really didn’t know anything about Continuations, so
maybe what I’m saying makes no sense at all, but I’d like to hear any
comments on the subject.
Ben