[Python-Dev] scoping and list comprehensions

Skip Montanaro skip@pobox.com (Skip Montanaro)
Wed, 30 May 2001 15:48:47 -0500


Regarding the issue of how list comprehensions should relate to their
environment, perhaps instead of modifying list comprehensions to make them
execute in new local scopes (or at least appear to) a better solution would
be to allow a new local scope to be introduced inline, sort of like in C:

    {
        int i;
	for (i=0; i < 10; i++) {
            dostuffwith(i);
	}
    }

While this might be used more for list comprehensions than other constructs,
I'm sure people will find a way to (ab)use it for other things as well.  I
don't see an obvious way of adding such functionality to Python without
introducing a new keyword though, which is going to make it difficult to get
past Guido:

    l = []
    scope:
        l = [i**2 for i in range(10)]
    print l

Hmmm, wait a minute, what if you terminated a block introducer (if or while
clause or try/except clauses) with something other than a colon?  (I'm just
thinking out loud, I don't think this is necessarily a good solution).

    if 1:		# no new scope introduced
        l = [i**2 for i in range(10)]
    print l

vs.

    if 1;		# new scope introduced for enclosed block
        l = [i**2 for i in range(10)]
    print l

That certainly has some line noise qualities about it, especially since
colons and semicolons are visually so similar, but does offer an alternative
to introducing a new keyword into the language.

Hmmm, wait another minute, perhaps you could simply overload def:

    l = []
    def:
        l = [i**2 for i in range(10)]
    print l

There's also the problem of how to export results from the scope, though
perhaps the new nested scope stuff provides a solution to that.  (I've
ignored them so far, so I can't tell...)

Would it be possible for the compiler to recognize the degenerate def: and
simply mangle any names that would clash instead of introducing an actual
new execution frame?  The above might be equivalent to

    l = []
    l = [__mangled_i**2 for __mangled_i in range(10)]
    print l

if 'i' already existed in the same scope.

Just thinking out loud.  I'm not sure any of these ideas is any better than
the current state of affairs.

Skip