[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Globals vs. Locals
- From: Uli Kusterer <witness.of.teachtext@...>
- Date: Fri, 5 Aug 2005 21:33:17 +0200
On Aug 5, 2005, at 2:37:53, Mike Pall wrote:
The reason is that 'local by default' does not mix well with
lexical scoping. The languages that use this either do not
have proper lexical scoping (and thus don't have the problem)
or need some ugly workarounds. It's a common language design
mistake (IMHO).
From what Google tells me, lexical scoping is the same as "static
scoping". This confuses me a little, because static scoping is what C
and other languages use (or is that where "proper" comes in?). Is the
scope operator in C++ (::) what you'd call an "ugly workaround"?
Could you perhaps elaborate what exactly you mean? While I've written
my share of parsers, lexers and bytecode compilers, I'm all self-
taught, and thus occasionally don't know the proper technical
terms... I tried to look it up in Wikipedia, but the article there
redirects to "scope", and doesn't at all clarify which of the
described concepts is "lexical scope".
Proper lexical scoping really requires that you have a choice
between mutating a binding (assignment) and creating a new
binding (declaration). Alas, the 'local by default' rule mixes
them and makes an assignment do both. Consequently you cannot
modify a variable in an outer scope with a simple assignment
(because that would create a new local variable with the same
name).
Unless of course you introduce an extra declaration to make up
for this. E.g. in Python this is the 'global' statement. But
this only allows you access to the outermost scope (module level).
This has little to do with proper lexical scoping.
Yeah, that's what HyperTalk did as well. On the other hand, what C
does is just use a global variable if it's present, unless you
declared a local variable of the same name in the current scope. I'm
a little confused why this can't be done in Lua, or why that wouldn't
be desirable. But I'm willing to learn.
The only real workaround in Python is to create a mutable
container (a list) in the outer scope. But then you have to use
list access and list assignment everywhere (x[1] = x[1] + 1).
Yuck. That's why closures in Python are ... uh ... unpopular.
Yeah, that would be ugly.
So far I thought it was safer if variables are local by default, so
code can't accidentally change another object's variables (e.g.
during a recursive call).
You can add metamethods to the globals table to catch undefined
reads/writes and print a warning or stop with an error. Lua 5.1
has a command line option '-w' that does this for undefined reads.
So, you're saying I could use a metamethod to actually turn off
automatic declaration of globals? That would be a way around it, I
guess.
Though right now, I'm still trying to find out whether I really
don't want automatic globals. The thing is this: The project for
which I'm investigating the use of Lua is aimed at beginning
programmers. As such, I'd need the language to not allow too many
casual bugs. One of the bugs I first thought of when looking at Lua
would be if the user forgot to add the "local" keyword inside one of
their functions. In that case, they'd get a global, and the code
would compile just fine, until they call another function that uses a
global of same name. Bugs like that would be hellishly hard for a
newbie to figure out.
Am I worrying too much? Can anyone give me a rationale why this
won't be that much of a problem? Automatic global creation comes in
handy when declaring new objects, because
foo = {}
automatically makes foo end up in global scope, just as a 'class'
declaration would.
BTW: Two weeks ago I found something related (well, a bit):
http://opal.cabochon.com/~stevey/sokoban/
This is an interesting comparison of dynamic languages for the
Java VM (Jython, Groovy, NetRexx, ...). The author wrote the
same program (Sokoban) in different languages and discusses the
pros and cons of each language (language design, not benchmarks).
He talks about the above problem, too.
I guess you're referring to the mentions of scope in the PNuts
chapter? Lua's way of always being global IMHO has the same problem,
just the other way round. While PHP and all similarly-scoped
languages require you to "pull in" global variables, Lua requires you
to explicitly deny that you want a global. Considering the majority
of variables in most programs seem to be locals, I'd personally take
a language I wrote in the direction of PHP and co.: The default would
be what's most frequently used. If you notice some code doesn't get
its correct value from a global, it's a fairly straightforward to
realize you need to pull in a global. OTOH, if writing one function
suddenly causes another completely unrelated one to return odd
values, it is quite difficult to a) locate the function that's
screwing up my global and b) to even get the idea that they might
both be using variables with the same names.
The author of these very interesting comparisons seems to have a
similar opinion:
>> Lexical scoping is lexical scoping -- you should always be able
to determine the nested lexical scopes by looking at the code
nesting. No exceptions.<<
Which I read as: Top level variables should be global, variables in
lower levels (e.g. functions) should be function-local.
However, being a programmer, I know how easy it is to pull in a
global variable in a language where assignment may implicitly declare
a variable. I might expect to be declaring and initializing a local,
while I'm in fact changing a pre-existing global. In light of that,
the ideal solution seems to me to either have a special section for
globals which will automatically be used by all other scopes (like
Pascal), or requiring explicit declaration of both kinds of variables.
Now, note I'm not dictating you change Lua to fit my whims. I'm
simply stating what problems I see. I may be overlooking some obvious
solutions to these problems.
Cheers,
-- M. Uli Kusterer
http://www.zathras.de