lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi,

Uli Kusterer wrote:
>  if I understood this correctly, the way variables work in Lua is  
> that they are global by default, and you explicitly declare those  
> local that you want to be thus. Is there any place where I can find  
> information on why it was designed this way, which is pretty much the  
> opposite of the major languages?

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).

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.

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.

To avoid making this a Python flamefest, here's an insight
from Ruby's language designer:

| [...] I needed block local variables, so I made the current local
| variable scoping rule, which is "when a new local variable
| appears first in a block, it is valid only in the block".
|
| And *I was wrong*. This rule is the single biggest design flaw
| in Ruby. You have to care about local variable name conflict,
| and you will have totally different result (without error)
| if they conflict.
|
| So, we are talking about a part of many-year-long effort of
| fixing this flaw. [...]
|
| [ http://www.rubygarden.org/ruby?LocalVariablesAndBlocks ]

>  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.


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.

Bye,
     Mike