2.1 bytecodehacks.closure

The module bytecodehack.closure allows the binding of a global reference in a function to a constant reference. It is similar to, but less general than, the attr_freeze module. It has a cuter interface, though.

A toy example:

from bytecodehacks.closure import bind_locals

def make_adder(n):
    def adder(x):
        return x+n
    return bind_locals(adder)

Then "make_adder(2)" returns a monadic function that adds 2 to its argument. This can be used to implement parameterized callbacks without using the dreaded `default argument hack' or wrapping the callback in a typing intensive and slow class method.

A more imaginative use is to bind in a mutable object; then state is preserved across calls. This contradicts what the language reference says about code objects, so it's a bit smelly. Never mind, it works (for now). An example, which will be familiar if you have read ``Structure and Interpretation of Computer Programs,'' is:

def make_balance(initial_amount):
    def withdraw(amount):
        if current[0]<amount:
            raise "debt!"
        else:
            current[0]=current[0]-amount
        return current[0]
    return bind(withdraw,current=[initial_amount])

This can be used as follows:

>>> from bytecodehacks.closure import make_balance
>>> W=make_balance(20)
>>> W(10)
10
>>> W(4)
6
>>> W(7)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "/home/mwh21/src/python/bytecodehacks/closure.py", line 98, in withdraw
    raise "debt!"
debt!
>>> W(2)
4

Cool, huh?

bind (func[, newname],var1=value1,...)
Returns a new function, optionally renamed to newname, where any reference to a global name `var1' in func is replaced by a reference to `value1'.

bind_locals (func)
Returns a new function where every reference to a global name in func is, if possible, replaced with a reference to the current value of a local variable of the same name in the calling context.

bind_now (func)
Similar to bind_locals, but also if a local variable with the same name as a global reference is not found, also looks for a global variable with that name.

make_adder (n)
The example seen above.

make_balance (n)
The other example seen above.

Send comments to mwh@python.net