On 26/11/20 7:07 pm, Guido van Rossum wrote:
Hmm... In the end I think the language design issue is with functions (and how they capture variable references rather than values)

Well, every other language I know of that has a notion of closures
captures variables exactly the same way that Python does. Either
they're all doing it wrong, or there's something unusual about
Python that makes the traditional approach inappropriate for it.

The reason I think the fault is with the for loop rather than
the functions is that there are other languages, such as Scheme
and Haskell, where the problem doesn't arise. The reason is that
the equivalent of a for loop in those languages is some kind of
mapping construct. For example the Python loop

    for x in items:
        add_button(lambda: do_action(x))

would be written in Scheme something like

    (map (lambda (x)
        (add_button (lambda () (do_action x)))))

Because the body is a function that gets called with the value of
the loop variable, it naturally creates a new binding on each
iteration, which then gets captured by the inner lambda.

having to write 'for new x in ...' is no better, because you'd still forget it.

I think it's still better (or at least more principled) than
relying on default argument abuse.

BTW, an advantage of requiring 'new' is that it could be applied
to other things. If it's allowed for any lvalue then you could
write things like

    while new x := something():
        ...

Maybe we should consider introducing a new kind of function that captures values instead?

People would then have to remember to use the right kind of
function.

Also I'm not sure the function is the right level of granularity.
Conceivably you could want a function to capture some names as
variables and others as values.

I've just been looking into the new lambda feature in C++11, and
it seems they've gone down this route. You get to specify which
variables from the enclosing scope get captured, and for each
one, whether it's captured by reference or by value.

If we were to add something like this to Python, variable capture
would have to be the default, so that existing code still works.
Then we just need a way to specify that particular names are
captured by value. Not sure how to do that in a way that doesn't
look ugly and/or obscure.

I'm reminded of something related that was discussed a while back:
a way for a function to have "constant" local names that are
evaluated at definition time, like default arguments, but not
part of the argument list. Kind of "default argument abuse
without the abuse". Maybe we should be revisiting that idea?

--
Greg
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/22UR26KJDSO74B26J7WDIQ4ZQZGWDNPO/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to