[Python-ideas] Explicit variable capture list
Guido van Rossum
guido at python.org
Tue Jan 19 20:01:42 EST 2016
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". Not
> > sure if that's the usual terminology, but the idea should be that a
> > reference to the value is captured, rather than (as Python normally does
> > with closures) a reference to the variable (implemented as something
> called
> > a "cell").
>
> 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*.
> This has the side-effect of exposing that as an argument, which may be
> underdesirable.
Indeed. It's also non-obvious to people who haven't seen it before.
> partial() can be used to work around that.
>
Hardly. Adding a partial() call usually makes code *less* obvious.
> > 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).
> 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.)
> that might be the semantics you are looking for:
>
> def func(a):
> static b = b # captures the value of b from the enclosing scope
>
Yeah, I think the OP proposed 'capture b' with these semantics.
> 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.
> def func(a):
> static:
> # Function initialisation section. Occurs once, when the
> # def statement runs.
> b = b # b on the left is local, b on the right is non-local
> # (just like in a parameter list)
>
Hm, this repetition of the name in parameter lists is actually a strike
against it, and the flexibility it adds (of allowing arbitrary expressions
to be captured) doesn't seem to be needed much in reality -- the examples
for the argument default pattern invariably use 'foo=foo, bar=bar'.
> # Normal function body goes here.
>
>
>
> But neither of these approaches would be good for lambdas. I'm okay with
> that -- lambda is a lightweight syntax, for lightweight needs. If your
> needs are great (doc strings, annotations, multiple statements) don't
> use lambda.
>
Yeah, the connection with lambdas in C++ is unfortunate. In C++, IIRC, the
term lambda is used to refer to any function nested inside another, and
that's the only place where closures exist.
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160119/e0a863b9/attachment-0001.html>
More information about the Python-ideas
mailing list