Tail Call Optimization as a Decorator
Kay Schluehr
kay.schluehr at gmx.net
Sun Feb 26 15:39:36 EST 2006
Crutcher wrote:
> This is fun :)
> {Note: I take no responsibilty for anyone who uses this in production
> code}
>
> #!/usr/bin/env python2.4
> # This program shows off a python decorator
> # which implements tail call optimization. It
> # does this by throwing an exception if it is
> # it's own grandparent, and catching such
> # exceptions to recall the stack.
>
> import sys
>
> class TailRecurseException:
> def __init__(self, args, kwargs):
> self.args = args
> self.kwargs = kwargs
>
> def tail_call_optimized(g):
> """
> This function decorates a function with tail call
> optimization. It does this by throwing an exception
> if it is it's own grandparent, and catching such
> exceptions to fake the tail call optimization.
>
> This function fails if (and only if) the decorated
> function recurses in a non-tail context.
> """
> def func(*args, **kwargs):
> f = sys._getframe()
> if f.f_back and f.f_back.f_back \
> and f.f_back.f_back.f_code == f.f_code:
> raise TailRecurseException(args, kwargs)
> else:
> while 1:
> try:
> return g(*args, **kwargs)
> except TailRecurseException, e:
> args = e.args
> kwargs = e.kwargs
> func.__doc__ = g.__doc__
> return func
>
> @tail_call_optimized
> def factorial(n, acc=1):
> "calculate a factorial"
> if n == 0:
> return acc
> return factorial(n-1, n*acc)
>
> print factorial(10000)
> # prints a big, big number,
> # but doesn't hit the recursion limit.
>
> @tail_call_optimized
> def fib(i, current = 0, next = 1):
> if i == 0:
> return current
> else:
> return fib(i - 1, next, current + next)
>
> print fib(10000)
> # also prints a big number,
> # but doesn't hit the recursion limit.
Hey Crutcher, what a beautifull and elegant hack! Have you already
contributed it to the Python cookbook?
Kay
More information about the Python-list
mailing list