
On Thu, 22 Feb 2001, Jeremy Hylton wrote:
I can't think of another lexically scoped language that allows an exec or eval to create a new variable binding that can later be used via a plain-old reference.
I tried STk Scheme, guile, and elisp, and they all do this.
One of the reasons I am strongly in favor of making import * and exec errors is that it stymies the efforts of a reader to understand the code.
Yes, i look forward to the day when no one will ever use import-* any more. I can see good reasons to discourage the use of import-* and bare-exec in general anywhere. But as long as they *do* have a meaning, they had better mean the same thing at the top level as internally.
If we look at your examples: >>> def f(): # x = 3 inside, no g() [...] >>> def f(): # x = 3 inside, nested g() [...] >>> def f(): # x = 3 outside, nested g()
In these examples, it isn't at all obvious to the reader of the code whether the module foo contains a binding for x or whether the programmer intended to import that name and stomp on the exist definition.
It's perfectly clear -- since we expect the reader to understand what happens when we do exactly the same thing at the top level.
Another key difference between Scheme and Python is that in Scheme, each binding operation creates a new scope.
Scheme separates 'define' and 'set!', while Python only has '='. In Scheme, multiple defines rebind variables: (define a 1) (define a 2) (define a 3) just as in Python, multiple assignments rebind variables: a = 1 a = 2 a = 3 The lack of 'set!' prevents Python from rebinding variables outside of the local scope, but it doesn't prevent Python from being otherwise consistent and having "a = 2" do the same thing inside or outside of a function: it binds a name in the current scope. -- ?!ng "The only `intuitive' interface is the nipple. After that, it's all learned." -- Bruce Ediger, on user interfaces