
[Ka-Ping Yee]
Hi all -- i've been reading the enormous thread on nested scopes with some concern, since i would very much like Python to support "proper" lexical scoping, yet i also care about compatibility.
There is something missing from my understanding here:
- The model is, each environment has a pointer to the enclosing environment, right?
The conceptual model, yes, but the implementation isn't like that.
- Whenever you can't find what you're looking for, you go up to the next level and keep looking, right?
Conceptually, yes. No such looping search occurs at runtime, though.
- So what's the issue with not being able to determine which variable binds in which scope?
That determination is done at compile-time, not runtime. In the presence of "exec" and "import *" in some contexts, compile-time determination is stymied and there is no runtime support for a "slow" lookup. Note that the restrictions are *not* against lexical nesting, they're against particular uses of "exec" and "import *" (the latter of which is so muddy the Ref Man said it was undefined a long, long time ago).
... It's good to start with a simple model for the user to understand; the implementation can then do funky optimizations under the covers so long as the model is preserved.
Even locals used to be resolved by dict searches. The entire model there wasn't preserved by the old switch to fast locals either. For example,
def f(): ... global i ... exec "i=42\n" ... i = 666 f() i 666
IIRC, in the old days that would print 42. Who cares <0.1 wink>? This is nonsense either way. There are tradeoffs here among: conceptual clarity runtime efficiency implementation complexity rate of cyclic garbage creation Your message favors "conceptual clarity" over all else; the implementation doesn't. Python also limits strings to the size of a platform int <0.9 wink>.
... The model described above is the approximately the one available in Scheme.
But note that eval() didn't make it into the Scheme std: they couldn't agree on its semantics or implementation. eval() is *suggested* in the fifth Revised Report, but there has no access to its lexical environment; instead it acts "as if" its argument had appeared at top level "or in some other implementation-dependent environment" (Dybvig; "The Scheme Programming Language"). Dybvig gives an example of one of the competing Scheme eval() proposals gaining access to a local vrbl via using macros to interpolate the local's value into the argument's body before calling eval(). And that's where refusing to compromise leads. utterly-correct-and-virtually-useless-ly y'rs - tim