[Python-ideas] Explicit variable capture list

Ryan Gonzalez rymg19 at gmail.com
Tue Jan 19 19:33:55 EST 2016



On January 19, 2016 5:51:15 PM CST, Steven D'Aprano <steve at pearwood.info> wrote:
>On Tue, Jan 19, 2016 at 03:10:35PM +0100, haael at 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?
>

No.

>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?
>

The given C++ lambda syntax copies the input parameters, so it would return 5.

This would return 6:

auto fun = [&a, &b, &c](int x, int y){ return a + b + c + x + y};

>
>
>> 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?

-- 
Sent from my Nexus 5 with K-9 Mail. Please excuse my brevity.


More information about the Python-ideas mailing list