[Python-Dev] LOAD_NAME & classes

Tim Peters tim.one@comcast.net
Thu, 25 Apr 2002 02:06:21 -0400


[Scott Gilbert, on Icon]
> A few corrections.  New variable names were local by default.

Ack!  You're right!  Years of stuffing in "local" decls made me forget why
they were recommended to begin with.

> The only way to get a global variable was to make a "global varname"
> statement at the global scope.

The difficulty being-- why explicit "local" was really recommended --that a
new global magically changes every *implicit* local vrbl of the same name
into a global.  This bit too when an implicit local happened to have the
same name as a new function added later, because function names are
automatically global.  Like:

procedure main()
    f()
    g()
end

procedure f()
    count := 1
    while count < 10 do count +:= 1
    write(count)
end

procedure g()
    write(len([2, 3, 4]) | "oops!")
end

procedure len(x)
   return *x
end

That prints

    10
    3

If you just happen to change the name of the "len" function to "count"
later:

procedure g()
    write(count([2, 3, 4]) | "oops!")
end

procedure count(x)
   return *x
end


it suddenly prints

    10
    oops!

instead (the expression

    count([2, 3, 4]) | "oops!"

becomes

    10([2, 3, 4]) | "oops!"

because the once-local "count" in f is suddenly global, and retains its
value of 10; then 10([2, 3, 4]) fails, and the alternative "oops!" is tried
and succeeds).

In real life these could be an absolute bitch to track down, so I always
used local.  Insert

    local count

at the top of f and everything's fine again.

> Icon gave you a None-like value, &null, for your variables if you
> hadn't already assigned to them somewhere.  So strictly speaking,
> you could read a variable before writing to it, and a declaration (first
> initialization) wasn't necessary the same way it is in Python.

I prefer Python distinguishing between None and unbound too; e.g., I'd much
rather have

    x := y

blow up at once if y hasn't been bound than to silently propagate &null (or
a Python None).  &null could travel *all over the place* before you finally
hit an expression where it didn't just silently fail (very few things in
Icon raise errors, as the 10([2, 3, 4]) example should have suggested to
onlookers <wink>).

> Using "local x" was strongly recommended because (a) you could use the
> -u switch of icont to warn you when you didn't declare your locals
> (usually from typos),

Unfortunately, -u doesn't complain about the "10 oops!" example above:  as
far as it's concerned, all variables were declared in that example.
Fortunately, it does complain about the original way of writing it, because
"count" is undeclared then.

> and (b) in case you forgot that you used the same name as a global
> somewhere else, or more likely you "link"ed with a file that had global
> declarations you weren't aware of.

Like an implicit "import *" in Python -- we're well aware of the dangers of
*that* around here <wink>.

> So it really wasn't so error prone.  (Icon's not even close to
> Perl in this regard.  :-)

Not for scope rules alone, no, although Perl sticking to explicit "my"
everywhere isn't much worse than Icon sticking to explicit "local"
everywere.