Variables#

A variable in Lua names a slot that holds a value. Slots are either local (lexically scoped to the enclosing block) or global (an entry in the environment table, _ENV). By default an unqualified name is global; write local in front almost every time.

For the values these names hold, see Types. For the keyword surface this builds on, see Syntax.

Declaration#

local declares a new variable in the current block. Bare = without local writes to the global environment.

x = 1            -- global; lives in _ENV until set to nil
local y = 2      -- local; lives until the block ends

Uninitialised locals are nil.

local a, b, c    -- all three are nil

Assignment#

= binds (or rebinds) names to values. Lua supports multiple assignment: the right-hand side is evaluated fully before any binding, which makes swap and tuple-style returns trivial.

local a, b = 1, 2
a, b = b, a          -- swap; right side computed first

local x, y, z = unpack({10, 20, 30})

Extra values on the right are discarded; missing values on the right are filled with nil.

local a, b, c = 1, 2          -- c is nil
local d, e    = 1, 2, 3       -- 3 is discarded

Scope#

Lua is lexically scoped. A local is visible from the next statement to the end of its enclosing block (function, doend, loop body, then / else arm).

do
  local secret = "rk"
  print(secret)        -- visible here
end
print(secret)          -- nil; the local is gone

A do block is the operator’s tool for carving out a private scope without a function call.

Variables captured by a closure (an inner function that refers to an outer local) extend that variable’s lifetime past the end of its block.

local function counter()
  local n = 0
  return function()
    n = n + 1
    return n
  end
end

local next = counter()
print(next(), next(), next())   -- 1  2  3

Globals#

Globals live in _ENV, a table that every chunk sees as its default environment. _G is a global alias to the top-level _ENV. Setting a global to nil removes it.

answer = 42            -- _ENV.answer = 42
print(_G.answer)       -- 42
answer = nil           -- removes the binding

Avoid globals. They cross module boundaries silently and make the program hostile to refactoring. local everything; export through a returned module table (see Runtime).

The strict Lua module (or a hand-rolled __index metatable on _ENV) traps reads of undeclared globals and turns them into errors at the point of use.

References#