[Python-Dev] 'stackless' python?
rushing at nightmare.com
rushing at nightmare.com
Mon May 17 11:46:29 CEST 1999
Tim Peters writes:
> [Sam]
> > Continuations are more powerful than coroutines, though I admit
> > they're a bit esoteric.
>
> "More powerful" is a tedious argument you should always avoid <wink>.
More powerful in the sense that you can use continuations to build
lots of different control structures (coroutines, backtracking,
exceptions), but not vice versa.
Kinda like a better tool for blowing one's own foot off. 8^)
> Suppose the driver were in a script instead:
>
> thing(5) # line 1
> print repr(saved) # line 2
> saved.throw(0) # line 3
> saved.throw(0) # line 4
>
> Then the continuation would (eventually) "return to" the "print repr(saved)"
> and we'd get an infinite output tail [...]
>
> and never reach line 4. Right? That's the part that Guido hates <wink>.
Yes... the continuation object so far isn't very usable. It needs a
driver of some kind around it. In the Scheme world, there are two
common ways of using continuations - let/cc and call/cc. [call/cc is what
is in the standard, it's official name is call-with-current-continuation]
let/cc stores the continuation in a variable binding, while
introducing a new scope. It requires a change to the underlying
language:
(+ 1
(let/cc escape
(...)
(escape 34)))
=> 35
'escape' is a function that when called will 'resume' with whatever
follows the let/cc clause. In this case it would continue with the
addition...
call/cc is a little trickier, but doesn't require any change to the
language... instead of making a new binding directly, you pass in
a function that will receive the binding:
(+ 1
(call/cc
(lambda (escape)
(...)
(escape 34))))
=> 35
In words, it's much more frightening: "call/cc is a function, that
when called with a function as an argument, will pass that function an
argument that is a new function, which when called with a value will
resume the computation with that value as the result of the entire
expression" Phew.
In Python, an example might look like this:
SAVED = None
def save_continuation (k):
global SAVED
SAVED = k
def thing():
[...]
value = callcc (lambda k: save_continuation(k))
# or more succinctly:
def thing():
[...]
value = callcc (save_continuation)
In order to do useful work like passing values back and forth between
coroutines, we have to have some way of returning a value from the
continuation when it is reinvoked.
I should emphasize that most folks will never see call/cc 'in the
raw', it will usually have some nice wrapper around to implement
whatever construct is needed.
-Sam
More information about the Python-Dev
mailing list