
On Tue, Jan 19, 2016 at 03:10:35PM +0100, haael@interia.pl wrote:
Hi
C++ has a nice feature of explicit variable capture list for lambdas:
int a = 1, b = 2, c = 3; auto fun = [a, b, c](int x, int y){ return a + b + c + x + y};
For the benefit of those who don't speak C++, could you explain what that does? Are C++ name binding semantics the same as Python's? Specifically, inside fun, does "a" refer to the global a? If you rebind global a, what happens to fun? fun(0, 0) # returns 6 a = 0 fun(0, 0) # returns 5 or 6?
This allows easy construction of closures. In Python to achieve that, you need to say:
def make_closure(a, b, c): def fun(x, y): return a + b + c + x + y return def a = 1 b = 2 c = 3 fun = make_closure(a, b, c)
I cannot tell whether the C++ semantics above are the same as the Python semantics here. Andrew's response to you suggests that it is not.
My proposal: create a special variable qualifier (like global and nonlocal) to automatically capture variables
"Variables" is an ambiguous term. I don't want to get into a debate about "Python doesn't have variables", but it's not clear what you mean here. Python certainly has names, and values, and when you talk about "variables" do you mean the name or the value or both?
a = 1 b = 2 c = 3 def fun(x, y): capture a, b, c return a + b + c + x + y
This will have an effect that symbols a, b and c in the body of the function have values as they had at the moment of function creation. The variables a, b, c must be defined at the time of function creation. If they are not, an error is thrown.
If I have understood you correctly, we can already do that in Python, and don't even need a closure: a, b, c = 1, 2, 3 fun = lambda x, y, a=a, b=b, c=c: a + b + c + x + y will capture the current *value* of GLOBAL a, b and c, store them as default values, and use them as the LOCAL a, b and c. You may consider it a strength or a weakness that they are exposed as regular function parameters: fun(x, y) # intended call signature fun(x, y, a, b, c) # actual call signature but if you really care about hiding the extra parameters, a second approach will work: from functools import partial a, b, c = 1, 2, 3 fun = partial(lambda a, b, c, x, y: a + b + c + x + y, a, b, c) If a, b, c are mutable objects, you can make a copy of the value: fun = partial(lambda a, b, c, x, y: a + b + c + x + y, a, b, copy.copy(c) ) for example. Does your proposal behave any differently from these examples? -- Steve