functional programming

Tim Peters tim_one at
Sat Feb 26 09:08:28 CET 2000

[posted and mailed]

> It's tail-call *optimization* that's un-Pythonic, as it's a gimmick
> supported by only a handful of widely unused <0.5 wink> languages
> and surprising to people coming from anything else:  damaging
> tracebacks would be Major Badness, much worse than the gain for the
> relative thimbleful of people who are uncomfortable coding loops
> etc.

[Denys Duchier]
> Tim's opinion notwithstanding, it seems to me that the only technical
> reason why tail call optimization _cannot_ (at least not easily) be
> supported by python

Note that I didn't give a technical reason:  my point is entirely about
pragmatics.  The introduction of TCO (tail-call opts) to a language that
doesn't have them necessarily involves tradeoffs.  Python isn't a blank
slate anymore.

> has to do with destructors for local objects.  The expectation is that
> an object created locally and assigned to a local variable has a
> dynamic extent that coincides with execution in its scope.  The timely
> finalization achieved by reference counting means that its destructor is
> invoked precisely when the scope is exited.

This applies much more to C++ than to Python.  Python doesn't define
anything about the lifetime of objects.  JPython doesn't even execute
__del__ methods.  CPython usually acts as you describe here, but it's not
guaranteed, and it's possible for a CPython stack frame to outlive the
function invocation that created it (the way that burns every C++ programmer
at least once in CPython is when an uncaught exception passes thru the
function, so that a reference to the stack frame lives on in the traceback
object:  locals can live "forever" then, while C++ guarantees to destruct
autos (in a defined order, even!) in its version of this).

> Tail call optimization would have to invoke it when the tail call is
> made.

Well, since the behavior you're trying to preserve is an implementation
accident, Guido wouldn't feel compelled to preserve it.  There's simply no
killer *technical* reason to avoid TCO in Python (although the
implementation would have to be cleverer than others have sketched, to avoid
e.g. treating what "looks like" a tail call as such in the try block of a
try/finally structure).

> I cannot help but add that the derogatory comment concerning tail call
> optimization

My assertion that TCO is a bad idea for Python doesn't condemn it in
general; to the contrary, TCO is *essential* in other languages I use.
Python isn't those languages.

> is not only shortsighted,

Actually, it's hindsighted <wink>:  I gave up fighting "jewel-like language"
battles over a decade ago.  If TCO hasn't taken over the world by now, it's
never going to.  Ditto Lisp, Scheme, Haskell, etc.  Doesn't mean I don't
love 'em; does mean I "had enough" of pouring energy into futile quests.
The good news is that Oz still has a chance <wink>.

> but also fallacious as it rests entirely on proof by popularity according
> to which we should all eat shit, since 50 trillion flies can't all be

I didn't know that flies relied on tracebacks to figure out why their
shitpile isn't where they expected to find it <wink>.

    y'rs  - tim

More information about the Python-list mailing list