[Python-Dev] Explicit Lexical Scoping (pre-PEP?)

Phillip J. Eby pje at telecommunity.com
Fri Jul 7 01:25:19 CEST 2006


At 01:00 AM 7/7/2006 +0200, Jan Kanis wrote:
>On Thu, 06 Jul 2006 18:28:12 +0200, 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.
>
>I agree this argument is not generally applicable in every case, but why
>not in this specific situation?

I'm saying that "just use a class" doesn't help in the incremental 
case.  If you happen to know *ahead of time* that you will need a callback 
to modify state, you can perhaps do this, just like you can always coast 
your car to a stop if you have enough advance notice.  However, sometimes 
you really want to have brakes.  :)


>>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 -
>
>I think this argument is a too general one. To me it is too close to
>"let's add every possible feature we can find, because it might be usefull
>to someone" :)

Not at all.  It's an argument regarding the incremental evolution of 
code.  Python tries to keep the growth of complexity in a code base 
relatively flat -- incremental effort should be rewarded with incremental 
benefit.  Discontinuities of complexity are to be avoided.

The classic example is "Hello world", where in Java you must learn about 
six or eight different things, but in Python it is just 'print "Hello 
world"'.  If you want to then make it a function, you indent it and add a 
'def'.  It is all very minimal and incremental, and for the most part, the 
things that people want to add to Python tend to be wherever 
discontinuities can occur.

It is also true that, because Python is already so well-designed, that 
these remaining feature areas tend to lean toward the minor and/or obscure: 
coroutines, conditional expressions, etc. etc.


>One of the things I like about python is that it doesn't do this, and
>therefore the manual stays relatively small and I don't have to remember
>all kinds of rarely used features to make best use of the language. (I
>assume this is not a point of debate. repeating: Python is not Lisp ;-) )

And one of the things that makes it not Lisp is that not everyone is free 
to go around and actually add the new syntax to support their use 
cases.  Guido must first be convinced.  Discussions like this one are how 
we convince him.  ;)


>>- or so it feels like to the person who's experiencing it.
>
>Have you ever been that person, or come across such a situation?

Many times.  The hard thing about trying to provide use cases for this is 
that of course you can always find another way to write it.  It's just that 
sometimes the nested function is a perfect solution at point in time A, and 
then at point in time B, a change in the program requires that the nested 
function mutate a bit of state, resulting in either a rewrite to do it the 
"right" way, or hacking mutable objects.

Both are user-experience discontinuities: a sudden sharp rise in effort 
compared to reward.  This then produces the perception of a "wart".  Yes, 
it's purely a superficial problem.  That's why it's called a "wart".  :)


>O, and I don't think the inc() example is a good one. In this incrementer
>the function call is all about the side effects, it's even in the name
>'increment'. Incrementing is useless unless you increment /something/, so
>this should be better implemented as a class.

Any example that's intended to motivate lexical scope modification is going 
to suffer from either being bogus due to oversimplification, or confusing 
due to application-specificity.  That doesn't make it something that 
doesn't happen, it's just that the circumstances of it happening are 
somewhat more organic.

By the way, I'm leaving out the people who have backgrounds in Lisp or 
Scheme and are trying to write it in Python.  I don't really care for Lisp, 
myself, although my Python has become increasingly functional over 
time.  Not because of Lisp (which I've never used apart from a few Emacs 
hacks 12 years ago, when I didn't even know what functional programming 
*was*), but because it's often the easiest way to do something.  At least, 
until you bump into the rebinding problem.

Personally, the idea to use a simple namespace object to store mutable 
variables as attributes seems rather appealing as a workaround solution in 
the absence of a rebinding operator.  The other solution I thought of was 
providing a function called 'rebind()' that could be used like this:

      rebind(x=23)

to change 'x' in the nearest enclosing scope.  This solves the problem 
without adding any syntax, and it's incremental at the point of use.



More information about the Python-Dev mailing list