Environments, _ENV and Globals

Lua 5.1/LuaJIT use setfenv(f, env) / getfenv(f) instead of _ENV.

Lua 5.5 (in development) is expected to add explicit global declarations for stricter scoping. Check the release notes.

-- Globals live in a table. In 5.2+, free names refer to fields of _ENV (normally _G).
print(_G.print == print)        --> true
_G["dynamic_" .. "name"] = 42
print(dynamic_name)             --> 42

-- Detect accidental globals
setmetatable(_G, {
    __newindex = function(_, k) error("attempt to create global '" .. tostring(k) .. "'", 2) end,
    __index    = function(_, k) error("attempt to read undefined global '" .. tostring(k) .. "'", 2) end,
})
-- (The "strict.lua" module from the Lua distribution's etc/ directory does this more carefully.)
-- _ENV (5.2+): change the environment for a scope
local function sandboxed()
    local _ENV = {print = print}     -- only print is visible here
    print("inside sandbox")
    -- os.exit()                     --> error: attempt to index a nil value (global 'os')
end
sandboxed()

-- Load a chunk with a custom environment
local env = {x = 10}
local chunk = load("y = x * 2", "config", "t", env)
chunk()
print(env.y)                         --> 20

-- Config files as Lua
local config = {}
loadfile("settings.lua", "t", config)()   -- settings.lua: width = 800; height = 600