[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