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

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