[Python-Dev] Explicit Lexical Scoping (pre-PEP?)
Guido van Rossum
guido at python.org
Fri Jul 7 02:10:59 CEST 2006
On 7/6/06, Phillip J. Eby <pje at telecommunity.com> wrote:
> Here's the reason I think this keeps coming up, and why Guido's "just use a
> class" argument doesn't really address the actual problem that's taking place.
(And note that I've recently gone on record as doubting that argument myself.)
> When you are writing some function, and you find yourself using a nested
> function because it's the closest match for something you're doing, there
> occasionally comes a point at which you realize that, gosh, you need to
> mutate something in an outer scope. At that point, your choices are to
> either kludge it with a mutable, or to reorganize the whole thing. Both of
> these *feel* like warts because they're making you do less-than-optimal
> things. Your mental "flow" is disrupted because the language is forcing
> you to work around it, rather than having a way of working with it.
Right. I'm actually not a big fan of the word "flow" -- it often
doesn't apply to the way I work myself, and it tends to emphasize the
needs of the writer at the expense of the reader. (Perl programmers
have excellent flow due to the many ways of doing things in that
language. 'nuff said.)
But I agree that the need for a refactoring like this to be a simple,
local thing is important. (Compare my argument for making print a
function -- which by the way received an applause at EuroPython once I
explained it, after getting boohs when the slide first went up.)
> This is a user experience issue, not a technical one. The fact that you
> can say, "you should've done it differently in the first place" doesn't do
> anything for your flow. In theory, you could design cars without any
> brakes, because people could just coast to a stop if they planned well
> enough in advance. ;-) In practice, you need the brakes because people
> often don't discover their need to stop until much later in the process.
I don't like the brakeless car example either. It is too extreme and
opens your argument up to easy objections (the similarity between the
cases isn't that great anyway).
> This is a flow issue that's specific to *incremental* development. What
> happens is that first you refactor the code in a function to include nested
> functions. The variable references don't change, you're just indenting
> some code. *Then*, it later comes up that you need to rebind a variable,
> and now you have to globally change the variable to make it work as a
> mutable instead, or else you have to refactor all the variables to be
> 'self.' references and put a class in somewhere.
> This destroys the flow of incrementally developing whatever it is you're
> developing, and makes you stop to do excise work. That's why being able to
> rebind a variable without redefining it is important.
Quite apart from the coder's flow, if the code is being developed
incrementally, there are probably readers reviewing it before and
after the refactoring. It's a lot easier to verify that a refactoring
is correct when it doesn't choose a completely different approach.
> In short: in *theory*, a rebinding operator or "nonlocal" declaration is
> unnecessary. In *practice*, having one seems quite useful every time you
> wander down the path that leads to having to rewrite your code just because
> the language won't let you do that one tiny thing -- or so it feels like to
> the person who's experiencing it.
There really is hardly any need to argue the point any more; I've said
that I will accept the feature if we can find a mutually acceptable
syntax. I still only see these two alternatives as viable: a new
keyword (nonlocal being my current favorite) or stretching the meaning
of global. After Andrew Koenig's Dijkstra reference I'm beginning to
think that the latter may actually be fine.
(Oh, and somebody can add "get rid of global" to PEP 3099 -- that
ain't gonna happen. :-)
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-Dev