Skip to content
AgileLogics
4 min read

Scope and Blocks

Prerequisites: Functions

A local variable is visible from its declaration to the end of the block it's in. Blocks are function bodies, loop bodies, if branches, and do ... end.

local x = "outer"

do
  local x = "inner"
  print(x)
end
print(x)

if true then
  local y = "only in the if"
  print(y)
end
print(y)
inner
outer
only in the if
nil
  • An inner local x shadows the outer one until the block ends.
  • y doesn't exist after the if — print(y) finds no local, looks for a global y, and gets nil.

Functions see enclosing locals

local count = 0

local function increment()
  count = count + 1
end

increment()
increment()
print(count)
2

A function can read and change the locals of the code around it. That's the foundation of closures (Level 2).

Declare before use

local function a()
  return b()
end

local function b()
  return "b"
end

print(pcall(a))
false	main.lua:2: attempt to call a nil value (global 'b')

Inside a, the name b didn't refer to a local yet (it's declared later), so Lua looked for a global b — which doesn't exist. For functions that call each other, declare the names first: local a, b then function a() ... end. (pcall catches the error so we can print it — see Error Handling in Level 2.)