>>> def foo (x):
def bar(y=None):
if y is None: return x
x = y
return x
return bar
>>> foo(3)
<function bar at 0xb7f7256c>
>>> _()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in bar
UnboundLocalError: local variable 'x' referenced before assignment
Andy's example will fail for both Python 2.x and 3.0 because 'x' in 'bar' is considered to be a local variable (which is the default unless you specify otherwise).
Python 2.x doesn't support rebinding a variable from a parent scope in its closures, so we can't make his example work without using some mutable variable type.
For Python 3.0 though, the new 'nonlocal' statement makes the function work as expected, updating the binding of 'x' in the parent scope.
>>> def foo (x):
... def bar(y=None):
... nonlocal x
... if y is None: return x
... x = y
... return x
... return bar
foo=lambda x: (lambda l=[x]: lambda y=None:
l[0] if y is None else l.__setitem__(0,y) or y)()A straight translation of the python program to SML (which should support closures):
Standard ML of New Jersey v110.67 [built: Thu May 1 12:26:45 2008]
-
- fun foo x = let
= fun bar y =
= case y of SOME(y) => let val x = y in x end
= | NONE => x
= in
= bar
= end;
val foo = fn : 'a -> 'a option -> 'a
- foo(3)
= ;
val it = fn : int option -> int
- foo(3)(NONE);
val it = 3 : int
- foo(3)(SOME(5));
val it = 5 : int
- foo(3)(NONE);
val it = 3 : int
-
Just because you support closures, doesn't mean you support modifying variables in the outer scope.
>>> def foo (x):
l = [x]
def bar(y=None):
if y is None: return l[0]
l[0] = y
return l[0]
return bar
>>> foo(3)
<function bar at 0xb7f7256c>
>>> _()
3