[Python-ideas] A "local" pseudo-function
Steven D'Aprano
steve at pearwood.info
Mon Apr 30 12:20:28 EDT 2018
On Sun, Apr 29, 2018 at 01:36:31PM +1000, Chris Angelico wrote:
[...]
> > While I started off with Python 1.5, I wasn't part of the discussions
> > about nested scopes. But I'm astonished that you say that nested scopes
> > were controversial. *Closures* I would completely believe, but mere
> > lexical scoping? Astonishing.
>
> I'm not sure how you can distinguish them:
Easily. Pascal, for example, had lexical scoping back in the 1970s, but
no closures. I expect Algol probably did also, even earlier. So they are
certainly distinct concepts.
(And yes, Pascal functions were *not* first class values.)
> What you expect here is lexical scope, yes. But if you have lexical
> scope with no closures, the inner function can ONLY be used while its
> calling function is still running. What would happen if you returned
> 'inner' uncalled, and then called the result? How would it resolve the
> name 'x'?
Failing to resolve 'x' is an option. It would simply raise NameError,
the same as any other name lookup that doesn't find the name.
Without closures, we could say that names are looked up in the following
scopes:
# inner function, called from inside the creating function
(1) Local to inner.
(2) Local to outer (nonlocal).
(3) Global (module).
(4) Builtins.
If you returned the inner function and called it from the outside of the
factory function which created it, we could use the exact same name
resolution order, except that (2) the nonlocals would be either absent
or empty.
Obviously that would limit the usefulness of factory functions, but
since Python 1.5 didn't have closures anyway, that would have been no
worse that what we had.
Whether you have a strict Local-Global-Builtins scoping, or lexical
scoping without closures, the effect *outside* of the factory function
is the same. But at least with the lexical scoping option, inner
functions can call each other while still *inside* the factory.
(Another alternative would be dynamic scoping, where nonlocals becomes
the environment of the caller.)
> I can't even begin to imagine what lexical scope would do in
> the absence of closures. At least, not with first-class functions.
What they would likely do is raise NameError, of course :-)
An inner function that didn't rely on its surrounding nonlocal scope
wouldn't be affected. Or if you had globals that happened to match the
names it was relying on, the function could still work. (Whether it
would work as you expected is another question.)
I expect that given the lack of closures, the best approach is to simply
make sure that any attempt to refer to a nonlocal from the surrounding
function outside of that function would raise NameError.
All in all, closures are much better :-)
--
Steve
More information about the Python-ideas
mailing list