[Python-Dev] A "real" continuation example
Tim Peters
tim_one at email.msn.com
Fri May 21 00:04:04 CEST 1999
[Tim]
> So what would this look like in Continuation Python?
[Sam]
> Here's my first hack at it. Most likely wrong. It is
> REALLY HARD to do this without having the feature to play with.
[Skip]
> The thought that it's unlikely one could arrive at a reasonable
> approximation of a correct solution for such a small problem without the
> ability to "play with" it is sort of scary.
Yes it is. But while the problem is small, it's not easy, and only the Icon
solution wrote itself (not a surprise -- Icon was designed for expressing
this kind of algorithm, and the entire language is actually warped towards
it). My first stab at the Python stack-fiddling solution had bugs too, but
I conveniently didn't post that <wink>.
After studying Sam's code, I expect it *would* work as written, so it's a
decent bet that it's a reasonable approximation to a correct solution as-is.
A different Python approach using threads can be built using
Demo/threads/Generator.py
from the source distribution. To make that a fair comparison, I would have
to post the supporting machinery from Generator.py too -- and we can ask
Guido whether Generator.py worked right the first time he tried it <wink>.
The continuation solution is subtle, requiring real expertise; but the
threads solution doesn't fare any better on that count (building the support
machinery with threads is also a baffler if you don't have thread
expertise). If we threw Python metaclasses into the pot too, they'd be a
third kind of nightmare for the non-expert.
So, if you're faced with this kind of task, there's simply no easy way to
get it done. Thread- and (it appears) continuation- based machinery can be
crafted once by an expert, then packaged into an easy-to-use protocol for
non-experts.
All in all, I view continuations as a feature most people should actively
avoid! I think it has that status in Scheme too (e.g., the famed Schemer's
SICP textbook doesn't even mention call/cc). Its real value (if any <wink>)
is as a Big Invisible Hammer for certified wizards. Where call_cc leaks
into the user's view of the world I'd try to hide it; e.g., where Sam has
def walk (self, x):
if type(x) == type([]):
for item in x:
self.walk (item)
else:
self.item = x
# call self.suspend() with a continuation
# that will continue walking the tree
call_cc (self.suspend)
I'd do
def walk(self, x):
if type(x) == type([]):
for item in x:
self.walk(item)
else:
self.put(x)
where "put" is inherited from the base class (part of the protocol) and
hides the call_cc business. Do enough of this, and we'll rediscover why
Scheme demands that tail calls not push a new stack frame <0.9 wink>.
the-tradeoffs-are-murky-ly y'rs - tim
More information about the Python-Dev
mailing list