[Python-ideas] several different needs [Explicit variable capture list]

Andrew Barnert abarnert at yahoo.com
Wed Jan 27 11:14:15 EST 2016


On Jan 27, 2016, at 04:41, Steven D'Aprano <steve at pearwood.info> wrote:

I think you're actually agreeing with me: there _aren't_ four different cases people actually want here, just the one we've all been talking about, and FAT is irrelevant to that case, so this sub thread is ultimately just a distraction. (We may still disagree about whether the one case needs a solution, or what the best solution would be, but we won't get anywhere by talking about different and unrelated things like this distraction.) But, in case I'm wrong about that, I'll answer your replies anyway:

>> On Tue, Jan 26, 2016 at 12:59:07PM -0800, Andrew Barnert via Python-ideas wrote:
>>> On Jan 26, 2016, at 11:40, Jim J. Jewett <jimjjewett at gmail.com> wrote:
>>> 
>>> (1)  Auxiliary variables
>>> 
>>>   def f(x, _len=len): ...
>>> 
>>> This is often a micro-optimization;
>> 
>> When _isn't_ it a micro-optimization? I think if it isn't, it's a very different case, e.g.:
> 
> I'm not sure why you call this "a very different case".

Because Jim's point was that FAT could do this automatically for him, so we don't need any syntax for it at all. That works for the optimization case, but it doesn't work for your case. Therefore, they're different.

Put another way: Without the default-value trick, his function means the same thing, so if he could rely on FAT, he could just stop using len=len. Without the default value trick, your function means something very different (a RecursionError), so you can't stop using enumerate=enumerate, with or without FAT, unless there's some other equally explicit syntax you can use instead.

Moreover, your case is really no different from his case #4, the case everyone else has been talking about: you want to capture the value of enumerate at function definition time.

>>> (2)  immutable bindings
>>> 
>>> once X
>>> final Y
>>> const Z
>> 
>> But a default value neither guarantees immutability, nor signals such 
>> an intent. Parameters can be rebound or mutated just like any other 
>> variables.
> 
> I don't think this proposal has anything to say about about either 
> immutability or bind-once-only "constants".

Jim insists that it's one of the four things people use default values for, and one of the things people want from this proposal, and that FAT can make that desire irrelevant. I think he's wrong on all three counts: you can't use default values for constness, nobody cares whether any of these new proposals can be used for constness, and FAT can't help anyone who does want constness.

>>> (3)  Persistent storage
>>> 
>>>   def f(x, _cached_results={}): ...
>> 
>>> I still think it might be nice to just have a way of easily opening a
>>> new scope ...
>> 
>> You mean to open a new scope _outside_ the function definition, so it 
>> can capture the cache in a closure, without leaving it accessible from 
>> outside the scope? But then f won't be accessible either, unless you 
>> have some way to "return" the value to the parent scope. And a scope 
>> that returns something--that's just a function, isn't it?
> 
> I'm not sure what point you think you are making here, or what Jim 
> meant by his comment about the new scope, but in this case I don't 
> think we would want an extra scope.

My point is that if you want to open a new scope to attach variables to a function, you can already do that by defining and calling a function. Which you very rarely actually need to do, so we don't need to make it any easier. So the fact that no variants of this proposal make it easier is irrelevant. 

>> Meanwhile, a C-style function-static variable isn't really the same 
>> thing. Statics are just globals with names nobody else can see. So, 
>> for a nested function (or a method) that had a "static cache", any 
>> copies of the function would all share the same cache,
> 
> Copying functions is, I think, a pretty rare and advanced thing to do. 

I'm not talking about literally copying functions. I'm talking about nested functions using the same code object for each closure that gets created, and methods using the same code and function object for every bound method that gets created. Using a C-style static variable in these cases means all your closures, or in all your methods from different instances, etc., which is not the same behavior as the other alternatives he suggested were equivalent.

This one, unlike his other points, isn't completely irrelevant. A C-style static declaration could actually serve some of the cases that the proposal is meant to serve. But it can't serve others, and it confusingly looks like it can serve more than it can, which makes it a confusing side track to bring up.



More information about the Python-ideas mailing list