11 ms·
One thing I didn't like after a quick look at Lua is that all variables are global by default. j = 10 -- global variable local i = 1 -- loca
by j4mie 14y ago
One thing I didn't like after a quick look at Lua is that all variables are global by default.
j = 10 -- global variable
local i = 1 -- local variable
( from http://www.lua.org/pil/4.2.html http://www.lua.org/pil/4.2.html )
Same with functions. To declare a function that is restricted to the local scope, you must explicitly use "local":
local f = function (...)
...
end
Can any Lua aficionados explain why this is the case? Surely a better design would be for variables to have local scope by default, and to require an explicit "global" prefix to be globally visible? Does this ever cause problems in real-world code?
- charltones 14y agoI did a fair amount of real world Lua a few years ago. This issue did start to bother me after my codebase grew. It is fairly easy to work around, mainly due to the very powerful metaprogramming facilities in Lua. See http://lua-users.org/wiki/DetectingUndefinedVariables http://lua-users.org/wiki/DetectingUndefinedVariables. I ended up adding a few lines of code to my own common library module which disallowed globals unless specifically declared with my own "declare" function.
- jballanc 14y agoThere's a page on the Lua users wiki that neatly summarizes the various arguments: http://lua-users.org/wiki/LocalByDefault http://lua-users.org/wiki/LocalByDefault Essentially, instead of asking "why global by default", you should have to explain "why local by default is a good idea". In practice, I've found it something easy enough to get over. You don't have to believe me, though...give the Lua Missions a try and see if you don't like Lua just a bit more than you thought you might: https://github.com/kikito/lua_missions https://github.com/kikito/lua_missions
- cygx 14y agoLocal or global by default is the wrong question to ask, because implicit declarations are a bad idea either way. Io - another minimal language - avoids the issue by having different operators for definition (:=) and assignment (=).
- ansible 14y agoThis discussion comes up on the mailing list occasionally. Well, the first answer to why we have global by default is history. Lua started out as a data description where global by default was a convenience. Local by default doesn't work so well either with nested scopes. Suppose we do have local by default and then consider this code: x = 0 function a() x = 1 function b() print(x) end end It is impossible to refer to a's x variable. This makes it harder to return a simple counter function, for example. This is regular Lua: function create_counter(initial_val) local count = initial_val or 0 local print_count = function() print (count) end local increment = function() count = count + 1 end return print_count, increment end Every time you call make_counter() you get a new pair of functions with their own internal count variable. See also PEP 3104 for more: http://www.python.org/dev/peps/pep-3104/ http://www.python.org/dev/peps/pep-3104/
- mangodrunk 14y agoEvery time you call make_counter() ... create_counter() If, local was the default, you would have: function create_counter(initial_val) count = initial_val or 0 print_count = function() print (global count) end increment = function() global count = global count + 1 end return print_count, increment end Something like that, it doesn't seem that much worse. Also, why wouldn't the print_count function inherit the scope of the containing context so you wouldn't even have to have the "global" keyword. function create_counter(initial_val) count = initial_val or 0 print_count = function() print (count) end increment = function() count = count + 1 end return print_count, increment end
- ansible 14y ago... create_counter() ... That's what I get for writing code on a small phone screen. :-) function create_counter(initial_val) count = initial_val or 0 print_count = function() print (global count) end increment = function() global count = global count + 1 end return print_count, increment end You might not want to use 'global', because that implies global scope. And in this case, this is not what was intended. For Python, keywords like 'outer' or 'nonlocal' were proposed. All in all, I'd be OK with 'nothing by default', but I'm also OK with global by default as it is now. If accidental creation of globals is a problem I can use the 'strict' module. function create_counter(initial_val) count = initial_val or 0 print_count = function() print (count) end increment = function() count = count + 1 end return print_count, increment end If local was the default, wouldn't the assignment to count in increment() create a new local variable (which is then discarded)?
- tomlu 14y agoThe reason is legacy. I personally lint all my code to prohibit global writes, and I wish I wouldn't have to. Hopefully by now language designers realise that anything-by-default is wrong. (That's right, I'm looking at you, Python.)
- anonymoushn 14y agoWhat linter do you use, and does it have vim integration?
- tomlu 14y agoI wrote my own. It basically imposes some restrictions on the way you are allowed to use Lua with respect to globals (with escape hatches). It also hooked into our Python-like import system. It checked illegal global writes and reads, illegal imports, unused imports and unused locals.
- anonymoushn 14y agoI also thought that this was a problem until I used Python and the "nonlocal" keyword didn't exist.