recursive decorator

Michele Simionato michele.simionato at gmail.com
Fri Sep 4 08:50:41 EDT 2009


On Sep 3, 6:41 pm, Ethan Furman <et... at stoneleaf.us> wrote:
>
> The original thread by Bearophile:
>    http://mail.python.org/pipermail/python-list/2009-May/711848.html

I have read the thread. What Bearophile wants can be implemented with
a bytecode hack, no
need for the decorator module. Let me call 'recur' the self-function,
like in Clojure.
You can define a decorator that makes "self-conscious" a recursive
function as follows:

# requires byteplay by Noam Raphael
# see http://byteplay.googlecode.com/svn/trunk/byteplay.py
from byteplay import Code, LOAD_GLOBAL, STORE_FAST, LOAD_FAST

def enable_recur(f):
    print f.func_code.co_names
    if 'recur' not in f.func_code.co_names:
        return f # do nothing on non-recursive functions
    c = Code.from_code(f.func_code)
    c.code[1:1] = [(LOAD_GLOBAL, f.__name__), (STORE_FAST, 'recur')]
    for i, (opcode, value) in enumerate(c.code[2:]):
        if opcode == LOAD_GLOBAL and value == 'recur':
            c.code[i+2] = (LOAD_FAST, 'recur')
    f.func_code = c.to_code()
    return f

## example of use

@enable_recur
def f(x):
    if x == 1:
        return 1
    else:
        return x*recur(x-1)

print f(4) # =>24


Please accept this without explanation since it would take me a lot of
time
to explain how it works. Just accept that bytecode hacks are
incredible
(and nonportable too) ;-)

                                    Michele Simionato



More information about the Python-list mailing list