Proposal: local variable declarations and type advice

Paul Rubin phr-n2002a at nightsong.com
Mon Feb 25 22:57:10 EST 2002


I thought I'd toss out the following two ideas:

1) add a local declaration, similar in syntax to Python's existing global
   declaration, but with meaning more like a local declaration in C or
   Perl.  It declares a variable for the scope of the current indent level:

     x = 2
     if mumble:
        local x
        x = 4       # inner scope
        frob(x)
     print x        # prints 2

   Any local declaration goes out of scope at the end of its indent level:

     # say there's no x in the current scope
     if mumble:
       local x
       x = 4
       frob(x)
     print x     # raises NameError

   Local can also be used in loop indexes:

     x = 3
     for local x in range(10):
        blah(x)
     print x    # still prints 3

     x = 3
     odds = [local x for x in range(10) if x%2 != 0]
     print x    # prints 3

   The list comprehension example should fix the persistent FAQ about
   why list comprehensions leave residue (i.e. variable bindings) around.
   It gives a way to clean up the residue, using a local declaration.
   It's similar to C++'s "for (int i = 0; i < 10; i++)" or perl's
   "foreach my $i { ...}".
   
2) Add a compiler option similar to Perl's "use strict", causing the
   compiler to flag with a warning any use of an undeclared variable
   (variables must be either declared local or declared global).  This
   should get rid of misspelled variable-name bugs, and some other
   bugs as well.  I constantly want something like this.

3) (Separate proposal from above): add optional type advice:

     local x(foo)     # advises Python implementation that x will
                      # only be bound to instances of class foo

   This is called "advice" rather than a "declaration" because it has
   no defined semantics and the compiler is free to ignore it, except
   that if the program acts as the advice says it will, it will work.

   Example 1:
     local x(int)    # advise Python that x is an int
     x = 3 + 2       # guaranteed to set x = 5 and work as you'd expect

   Example 2:
     local x(int)
     x = "banana"    # implementation-dependent behavior

   Some ways Python can handle example 2:

   1a) Compiler does enough static analysis to flag the "banana" assignment
      as a compile time error

   1b) Compiler doesn't flag; interpreter raises runtime TypeError exception.

   2) Compiler doesn't flag; interpreter assigns "banana", i.e. the
      advice is completely ignored and does nothing, the program works
      exactly the same way it does now without the advice

   3) Compiler doesn't flag, interpreter has totally undefined behavior.
      It can work normally, or crash, or delete all your files, etc.
      The idea is that an optimizing compiler can believe the advice and
      generate code based on x always being an int (it can put it in a
      register, perform native machine code arithmetic on it etc).

The idea is that you'd choose between 1a/1b and 3 as a compile time
option--you'd choose 1a/1b for debugging or 3 for speed.  Normally you
wouldn't choose 2--you wouldn't put the type advice into your program
unless you wanted it to mean something--so 2 is really just a special
case of 3 (i.e. it's one possible thing the implementation can do
without warning you).

Python has grown from a tiny acorn to a healthy young tree.  I believe
any changes and additions to its design should be made with the idea
that it may become a mighty oak one day, i.e. that it will have serious
native-code optimizing compilers.   Language design changes should work
toward that goal, or at least not impede it.



More information about the Python-list mailing list