[Python-Dev] The baby and the bathwater (Re: Scoping, augmented assignment, 'fast locals' - conclusion)

Boris Borcic bborcic at gmail.com
Thu Jun 15 19:41:03 CEST 2006

[this is bytes of an oversized put-all-into-it intervention. A possibly expanded 
version will be submitted on clp with local followup before a couple days]

Josiah Carlson wrote:

 >> I'd say a first step in convincing me I am wrong would be to show me 
examples of
 >> object methods of the standard library that are recursive, and cut out for
 >> recursion.

 > Actually, I don't believe that is necessary. I've shown that you would
 > get better performance with a non-recursive function and passing two
 > arguments, than you would passing one argument with scoping tricks to
 > get the second.

Assuming my aim was purely performance clearly stretches the hints I gave that I 
wasn't unconcerned by it. Taking ground on this to unwarrantedly suppose that my 
methodology was deficient, rectify it, and then dictate the "necessary" 
conclusions I find... er, preposterous seems balanced, "thought police" not 
totally unwarranted.

What I am doing. After a long while of relaxed ties with the latest Python, and 
upon observing at http://pythonsudoku.sourceforge.net/, an imo hugely bloated 
code-base concerned with sudoku, I found it a convenient means to refamiliarize 
myself with some leading edge Python, to explore the manifold of equivalent 
programs defined a priori by the invariant constraint :

"universal sudoku solver in +-pure python, ~10ms/problem, and ~60 LOCS total".

At present I must have examined about 50 versions, some unfinished, some 
differing only by details you would call "trivial", others massively differing 
by choice of key data types and modules. And algorithmic details, readability, 
ease of debugging, obviousness, speed, concision... in brief, differing in 
beauty as I see it.

A minute example that this approach works (given my aims) is that has 
signification to me, such a leading edge detail as the news that 
unicode.translate() had been accelerated during the latest 2.5 sprint.

While I've not excluded code profiling as a tool to use at some point, I don't 
think it is adapted at this stage; timeit does what I need, whenever I want to 
compare speed of versions differing by one factor that usually implies many 
local changes. As made clear (I hope) speed isn't the primary or unique concern 


This said...

This said, first : I deny you have or ever had real ground to refuse legitimacy, 
motivation, efficiency or methodological soundness to my approach.

Second : I tell you with good ground that under these (admittedly peculiar, but 
quite intense) "lighting conditions" the compiler "feature" that's the cause of 
the present debate stands out like a sore thumb.

 >>> Given [...]
 >>> you are not likely to find me agreeing with you about
 >>> augmented assignment and/or lexically nested scopes.

 >> I see. Thanks for the background. Background for backround, let me just say 
 >> python hadn't yet grown a lambda when I first played with it. May I read your
 >> last statement as acknowledging that I am not so much asking for a door to be
 >> created, than asking for a naturally builtin door, not to be locked by special
 >> efforts ?

 > No, you may not.  There are two options for the Python compiler/runtime
 > behavior when faced with an augmented assignment for a name not yet
 > known in this particular lexical scope but known in a parent scope:

"Special efforts" I maintain. Here they hide in the choice of hypothesis and 
tensing to artificially exclude from the "use case", what is in fact the most 
likely situation whenever the compiler/runtime follows to its end the codepath 
you advocate.

Indeed, that situation is almost bound to be the case *if* the resulting error 
message acurately describes the user's real error *and* the latter is not prey 
to foolish coding habits (further than the in-your-opinion fatally foolish habit 
that's assumed by hypothesis : and I guess this explains your bias here, 
crediting *presumed* fools with more than their share of foolishness - circular 

As relates to this "background use case", what I advocate amounts to 
substituting "reference to unknown global variable" for "local variable 
referenced before initialization". An error message for another, both bringing 
attention to the right problem.

 > to expect whenever the "compiler/runtime" system
 > assume you meant the name in the parent scope, or assume you made a
 > mistake. The current state of affairs (for all released Pythons with
 > augmented assignment) is to assume that you meant the local scope. Why?
 > Because while allowing the augmented assignment would make your life
 > easier in this case, the error would "pass silently"

Yeah, this all quite fits what I had anticipated when I spoke of my "deeply felt 
aversion for whatever resembles a constraining curriculum of errors to make (or 
else I would program in Java)". But its true I hadn't anticipated the concurrent 
case of errors one is required to make simultaneously ;)

 > when it was an
 > actual error (a not uncommon case),

I guess your insistence on the rightful methodology entitles me to enquire in 
turn on your choice of tool to establish the relative frequency of said case ?

Given that I've shown that it *is* the exceptional case, structurally speaking !

 > which is a bit of a no-no,

What I would have believed a /bit/ of a no-no for Python, is to turn away from 
the "consenting adults" spirit to go the way of so many other programming languages.

Picture of the latter way : - As a matter of course, to place the virtue of 
catching errors early, before the virtue of following programmers' legitimate 
intentions. - Designing for assumed chronic lusers in need of being protected by 
the compiler from shooting themselves in the foot.

(Ok, this relates to a single marginal "feature", whose closest peer in 
characteristic is maybe the strange quirks of sum() - a quite distant peer).

 > and the
 > case when you meant the parent scope is easily worked around.

Did I ever deny this ? I actually started by showing how the runtime (friendly 
as opposed to the compiler) taught me a workaround I did not yet know (to the 
contrary of the flurry of workarounds you've cited since, who knows why)

To pythondevers, my concluding message will go thus, in mixed metaphors : beware 
of not throwing away with the "bathwater" - the cultural intrusion of hordes of 
Scheme immigrants who take closures for the first word of Creation, the "baby" : 
an *original* space in Python, well moderated but roomy enough for 
Python-natives to evolve a python-inspired style in closures with some flesh to 
it. Which means freedom from the nuisance barkings of an obnoxious javanese 
watchdog named "Sin".


Boris Borcic
"On naît tous les mètres du même monde"

More information about the Python-Dev mailing list