20

Apparently, there's been a big brouhaha over whether or not Python needs tail-call optimization (TCO). This came to a head when someone shipped Guido a copy of SICP, because he didn't "get it." I'm in the same boat as Guido. I understand the concept of tail-call optimization. I just can't think of any reason why Python really needs it.

To make this easier for me to understand, what would be a snippet of code that would be greatly simplified using TCO?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason Baker
  • 192,085
  • 135
  • 376
  • 510

4 Answers4

16

Personally, I put great value on tail call optimization; but mainly because it makes recursion as efficient as iteration (or makes iteration a subset of recursion). In minimalistic languages you get huge expressive power without sacrificing performance.

In a 'practical' language (like Python), OTOH, you usually have a lot of other constructions for almost every situation imaginable, so it's less critical. It is always a good thing to have, to allow for unforeseen situations, of course.

Personally, I put great value on tail call optimization; but mainly because it makes recursion as efficient as iteration (or makes iteration a subset of recursion). In minimalistic languages you get huge expressive power without sacrificing performance.

In a 'practical' language (like Python), OTOH, you usually have a lot of other constructions for almost every situation imaginable, so it's less critical. It is always a good thing to have, to allow for unforeseen situations, of course.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Javier
  • 60,510
  • 8
  • 78
  • 126
  • That's about what I suspected, but I figured there must be a bigger reason for it. I suppose I was wrong. – Jason Baker May 21 '09 at 12:21
  • 1
    but remember that those 'minimalistic languages' that i mention (Lua and Scheme, for example) are usually both nicer and much faster than Python. in part because having reliable tail call optimization frees your mind and makes programs clearer. unfortunately, i don't know any one as practical as Python. – Javier May 21 '09 at 14:09
6

If you intensely want to use recursion for things that might alternatively be expressed as loops, then "tail call optimization" is really a must. However, Guido, Python's Benevolent Dictator For Life (BDFL), strongly believes in loops being expressed as loops -- so he's not going to special-case tail calls (sacrificing stack-trace dumps and debugging regularity).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
5

Tail-call optimization makes it easier to write recursive functions without worrying about a stack overflow:

def fac(n, result=1):
        if n > 1:
                return fac(n - 1, n * result)
        return result

Without tail-call optimization, calling this with a big number could overflow the stack.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zifre
  • 26,504
  • 11
  • 85
  • 105
  • 3
    Standard academic example. Any example with real world usage? – ebo May 20 '09 at 22:04
  • 7
    in fact, this isn't tail recursive. the multiplication is in the tail, not the recursion. – Javier May 20 '09 at 22:15
  • 3
    def fac(n): return reduce(operator.mul, range(1, n+1)) – John Fouhy May 20 '09 at 22:24
  • 5
    @Javier, the multiplication is in the tail, and there is no "pending" operation to perform, once the recursive call returns. Hence, that makes it tail recursive. Please correct me if I am wrong. –  May 21 '09 at 03:50
  • 2
    @Amit: He was correct originally, I changed the example. But even with the original, a smart compiler could have optimized it. – Zifre May 21 '09 at 20:28
  • 1
    @Zifre: right, the new form is so widely recognized as efficient, that Scheme purists refer to this as 'iteration, not recursion', since the TCO produces the same code as a while(){...} loop – Javier May 22 '09 at 13:47
  • 3
    @ebo: "Standard academic example. Any example with real world usage?" Asynchronous state machines, commonly seen in F# server code. – J D Jan 30 '12 at 21:34
1

Guido recognized in a follow up post that TCO allowed a cleaner the implementation of state machine as a collection of functions recursively calling each other. However in the same post he proposes an alternative equally cleaner solution without TCO.

barracel
  • 1,831
  • 13
  • 24