| But what if C(1) and C(2) are not exactly the same size? Say you want to resume continuation K, which has a stack of some size N. The current thread has a stack of size M. If M >= N, everything is fine: you can safely overwrite the current stack with K's stack. If M < N, recurse until M >= N. You could try to snapshot the entire C stack to get around this, including the outermost C frames. Indeed! This is a solution. It wouldn't be acceptable... I like doing unacceptable things in my programs. It's the best part of programming, really. There are a lot of solid arguments against call/cc. I think the most persuasive argument in favor of call/cc is that you become more powerful. Whatever metric you use to measure power, call/cc will improve it: Smaller code, less time spent writing code, and you can even write algorithms that you otherwise would not be able to. Personally, I want call/cc in order to be able to use choose and fail. It's the ability to write programs that are guaranteed to never call fail(). pg explains it well: "For example, this is a perfectly legitimate nondeterministic algorithm
for discovering whether you have a known ancestor called Igor: Function Ig(n)
if name(n) = ‘Igor’
return n
if parents(n)
return Ig(choose(parents(n)))
fail
The fail operator is used to influence the value returned by choose. If we
ever encounter a fail, choose would have chosen incorrectly. By definition choose
guesses correctly."Call/cc makes this possible. There are a lot of fun things to do. The last few chapters of On Lisp show some particularly interesting sketches. |
The size of the continuation's stack doesn't matter for the problem I described, it's the size of the stack "underneath" your continuation that matters (ie. C(1) and C(2) above).
If C(2) > C(1) there is no way to shrink C(2) such that the continuation's stack can be copied into the right place.
> I like doing unacceptable things in my programs. It's the best part of programming, really.
What you do in your programs is up to you! But nobody else is going to use a C library that messes with the execution state of its callers (unless that is the point of the library, which it isn't with Lua).