[Python-ideas] Explicit variable capture list
Steven D'Aprano
steve at pearwood.info
Wed Jan 20 19:10:32 EST 2016
On Tue, Jan 19, 2016 at 05:01:42PM -0800, Guido van Rossum wrote:
> On Tue, Jan 19, 2016 at 4:37 PM, Steven D'Aprano <steve at pearwood.info>
> wrote:
>
> > On Tue, Jan 19, 2016 at 08:47:28AM -0800, Guido van Rossum wrote:
> >
> > > I think it's reasonable to divert this discussion to "value capture".
[...]
> > If I understand you correctly, that's precisely what a function default
> > argument does: capture the current value of the default value expression
> > at the time the function is called.
>
> I think you misspoke here (I don't think you actually believe what you said
> :-).
>
> Function defaults capture the current value at the time the function is
> *define*.
Oops! You got me. Yes, I meant defined, not called.
[...]
> > > The best syntax for such capture remains to be seen. ("Capture" seems to
> > > universally make people think of "variable capture" which is the opposite
> > > of what we want here.)
> >
> > If I recall correctly, there was a recent(?) proposal for a "static"
> > keyword with similar semantics:
> >
> > def func(a):
> > static b = expression
> > ...
> >
> > would guarantee that expression was evaluated exactly once.
>
> Once per what? In the lifetime of the universe? Per CPython process start?
> Per call?
>
> J/K, I think I know what you meant -- once per function definition (same as
> default values).
That's what I mean. Although, I am curious as to how we might implement
the once per lifetime of the universe requirement :-)
> > If that
> > evaluation occurred when func was defined, rather than when it was first
> > called,
>
> (FWIW, "when it was first called" would be a recipe for disaster and
> irreproducible results.)
It probably would be a bug magnet. Good thing I'm not asking for that
behaviour then :-)
[...]
> > Scoping rules might be tricky to get right. Perhaps rather than a
> > declaration, "static" might be better treated as a block:
> >
>
> Why? This does smell like a directive similar to global and nonlocal.
I'm just tossing the "static block" idea out for discussion, but if you
want a justification here are two differences between capture/static
and global/nonlocal which suggest they aren't that similar and so we
shouldn't feel obliged to use the same syntax.
(1) global and nonlocal operate on *names*, not values. E.g. after
"global x", x refers to a name in the global scope, not the local scope.
But "capture"/"static" doesn't affect the name, or the scope that x
belongs to. x is still a local, it just gets pre-initialised to the
value of x in the enclosing scope. That makes it more of a binding
operation or assignment than a declaration.
(2) If we limit this to only capturing the same name, then we can only
write (say) "static x", and that does look like a declaration. But maybe
we want to allow the local name to differ from the global name:
static x = y
or even arbitrary expressions on the right:
static x = x + 1
Now that starts to look more like it should be in a block of code,
especially if you have a lot of them:
static x = x + 1
static len = len
static data = open("data.txt").read()
versus:
static:
x = x + 1
len = len
data = open("data.txt").read()
I acknowledge that this goes beyond what the OP asked for, and I think
that YAGNI is a reasonable response to the static block idea. I'm not
going to champion it any further unless there's a bunch of interest from
others. (I'm saving my energy for Eiffel-like require/ensure blocks
*wink*).
--
Steve
More information about the Python-ideas
mailing list