Let me start (n+1)-th thread about "global by default" feature of Lua.
My suggestion is to replace "global by default" approach with "nothing by default" by introducing special syntax for accessing global variables:
$print("Hello world") -- ok
print("Hello world") -- syntax error: referencing undeclared variable "print"
_G.print("Hello world") -- syntax error: referencing undeclared variable "_G"
"$" is not a part of an identifier.
"$" is a lexem (for example, there could be a space between "$" and global variable name).
"$" is absolutely the same as "_ENV." but is more comfortable to use.
Why do we need this?
"$globalvar" notation introduces two separate namespaces: one for globals and one for locals/upvalues.
As a result of this separation, most of variable name typos will be detected at compile time.
Although global name typos will not be detected ($math.sin -> $moth.sin), the most of identifiers in properly-written Lua programs are locals.
Currently, writing Lua programs without "global-nil-alarmer" (such as "strict.lua") is practically impossible (because typos in local variable names are silently converted to globals).
"$print" contains more symbols than "print", and you have to press SHIFT on your keyboard to type "$", but this is not a drawback.
Instead, there is a point in it: users would have to pay attention to slow global access.
More finger moves = more CPU time to access.
So, we are adding "ergonomical motivation" to cache globals in Lua programs :-)
Polluting of global namespace is already discouraged in Lua, so introducing "$" prefix for globals is the next step in that direction.
It is a polite way to say: "use globals only when they are really needed".
The "$globalvar" notation will solve problem with globals occasionally shadowed out by locals or upvalues:
local function sort_desc(table)
table.sort(table, function(a, b) return a>b end) -- very popular newcomers' mistake
The "$globalvar" notation will make the difference between "monkey-patch-friendly code" and "monkey-patch-unfriendly code" more easy to see.
BTW, "_ENV" could be removed from Lua as "$" could do the same (with some modifications in the parser to interpret "$" either as "_ENV." or as "_ENV"):
$print() -- instead of print()
$.print() -- instead of print()
local env = $ -- instead of local env = _ENV
$[key] = value -- instead of _ENV[key] = value
function sndbx($) -- instead of function sndbx(_ENV)