No Let-over-Lambda in Python 2 :(
Standard idiom in LISP (or in this case, Scheme), Let over Lambda (also the title of an impressive book on LISP macros by Doug Hoyte):
(define (mkcounter) (let ((n 0)) (lambda () (begin (set! n (+ 1 n)) n))))
What does it do? It returns a function that returns 1, 2, 3, ... when called repeatedly. It's a way of keeping state in a world of functions. Don't confuse it with C's
static
Variables inside functions.mkcounter
constructs a new counter object for each invocation, sowould print(define c1 (mkcounter)) (define c2 (mkcounter)) (c1) (c1) (c1) (c2) (print (c1)) (print (c2))
4
2
.
An attempt to reconstruct this in Python 2.x:
def mkcounter(): n = 0 def _inner_(): n = n+1 return n return _inner_ c1=mkcounter() print c1()
fails with
UnboundLocalError: local variable 'n' referenced before assignment
, which is somewhat confusing, sincen
is visible in_inner_
if then = n+1
line is removed.
The impossibility of LoL in Python has been pointed out in PEP-3104 but was only fixed in Python 3. In Python 3 it's possible to reconstruct LoL by the dubiously namednonlocal
directive:def mkcounter(): n = 0 def _inner_(): nonlocal n n = n + 1 return n return _inner_ c1=mkcounter() print(c1())
Mon, 15 Jul 2013
[/projects]
permanent link