[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