Declaring Variables in Lua
Understand global vs local variables and naming conventions.
Declaring Variables in Lua is a free Lua Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Global vs Local Variables
In Lua, variables are global by default. Writing x = 10 without the local keyword creates a global variable accessible from anywhere. Using local x = 10 restricts the variable to the current block and its nested blocks.
Always prefer local for performance and safety. Accessing a local variable is faster than a global because globals require a hash table lookup in the _G table.
x = 100 -- global variable
local y = 200 -- local variable
do
local z = 300 -- block-local
print(x, y, z) -- 100 200 300
end
print(x, y) -- 100 200
print(z) -- nil (out of scope)The local Keyword
The local keyword declares a variable scoped to the nearest enclosing block: a function body, a do...end block, a loop body, or a file chunk. Local variables are created at the line they're declared and cease to exist at the end of their block.
You can declare multiple locals on one line and initialize them simultaneously. Uninitialized locals default to nil.
local a, b, c = 1, 2, 3
print(a, b, c) -- 1 2 3
local d, e = 10 -- e is nil
print(d, e) -- 10 nil
local f -- nil until assigned
f = 42
print(f) -- 42Variable Naming Conventions
Lua identifiers follow these rules: they must start with a letter or underscore, followed by letters, digits, or underscores. Lua is case-sensitive, so Value, value, and VALUE are three different variables.
By convention: use camelCase or snake_case for regular variables, UPPER_CASE for constants, and prefix private module fields with an underscore. Avoid single-letter names except for loop counters.
local myVariable = 1 -- camelCase
local my_variable = 2 -- snake_case
local MAX_SIZE = 100 -- constant convention
local _private = "hidden" -- private convention
-- Case sensitivity demo
local lua = "lower"
local Lua = "upper"
print(lua, Lua) -- lower upperThe _G Global Table
All global variables in Lua live in a special table called _G. Writing x = 10 is equivalent to _G.x = 10. You can inspect all globals by iterating _G, which is handy for debugging but dangerous for production code.
In Lua 5.2+, _ENV is the actual environment table and _G is initialized to point to it. Understanding this lets you sandbox code by replacing _ENV.
myGlobal = 42
print(_G.myGlobal) -- 42
-- Setting via _G is the same as direct assignment
_G.another = "hello"
print(another) -- hello
-- Counting globals (many built-ins exist)
local count = 0
for k in pairs(_G) do count = count + 1 end
print("Globals:", count)Multiple Assignment
Lua supports multiple assignment: you can assign several variables in a single statement. The right-hand side is evaluated first, then assigned left to right. If there are more variables than values, extras get nil. If there are more values than variables, extras are discarded.
This makes swapping variables trivial without a temporary variable.
-- Swap without temp variable
local a, b = 10, 20
a, b = b, a
print(a, b) -- 20 10
-- More variables than values
local x, y, z = 1, 2
print(x, y, z) -- 1 2 nil
-- More values than variables
local p, q = 1, 2, 3 -- 3 is discarded
print(p, q) -- 1 2Scope and Block Boundaries
Lua's block delimiters are: do...end, function bodies, if/elseif/else...end, while...end, repeat...until, and for...end. Each creates a new scope level. do...end blocks are useful purely for limiting scope without any other logic.
A local declared in a for loop header is scoped to the loop body — it doesn't leak outside.
for i = 1, 3 do
local msg = "item " .. i
print(msg)
end
-- print(i) -- would be nil, i is gone
-- print(msg) -- would be nil, msg is gone
-- do...end for manual scoping
do
local temp = expensive_computation or 0
print(temp)
end
-- temp is nil hereConstants: The local Convention
Lua has no built-in const keyword. The convention is to use UPPER_CASE names and local to signal that a value shouldn't change. Placing constants at the top of a module as locals also gives the JIT compiler a hint that these values are stable.
For true immutability, you can use a proxy table with __newindex that raises an error on modification — we'll cover that in the metatables lesson.
local MAX_RETRIES = 3
local PI = 3.14159265358979
local APP_VERSION = "1.0.0"
-- Use them as read-only by convention
local area = PI * 5 * 5
print(area) -- 78.539...
print(MAX_RETRIES) -- 3Variable Shadowing
Shadowing occurs when an inner scope declares a local with the same name as an outer variable. The inner declaration creates a completely new variable that hides the outer one within its scope. The outer variable is unchanged and becomes visible again after the inner scope ends.
Shadowing can be confusing; prefer unique names across nested scopes, but sometimes it's intentional (e.g., reusing loop variable names in nested loops).
local x = "outer"
do
local x = "inner" -- shadows outer x
print(x) -- inner
end
print(x) -- outer (unchanged)
local n = 10
for n = 1, 3 do -- loop n shadows outer n
print(n) -- 1, 2, 3
end
print(n) -- 10 (outer unchanged)Avoiding Global Pollution
Accidental globals are a common Lua bug: mistyping a local variable name creates a new global silently. The strict.lua module (commonly included in projects) catches undeclared global reads and writes by adding a metatable to _G.
A simpler approach: always use local and run luac -p or a linter like luacheck to detect accidental globals before runtime.
-- Dangerous: typo creates a global silently
local counter = 0
coutner = 5 -- typo! creates global 'coutner'
print(counter) -- 0 (not 5!)
print(coutner) -- 5 (the typo global)
-- Fix: always use local keyword
local score = 0
score = 10 -- assigns to existing local
print(score) -- 10Nil Assignment Deletes Globals
Setting a global to nil removes it from _G, freeing memory. This is the correct way to "delete" a global. For locals, simply letting them go out of scope achieves the same effect — the garbage collector reclaims the memory.
Be careful when passing nil in multiple assignment: it can truncate the argument list in some contexts, particularly with function calls on the right-hand side.
myGlobal = "exists"
print(myGlobal) -- exists
print(_G.myGlobal ~= nil) -- true
myGlobal = nil
print(myGlobal) -- nil
print(_G.myGlobal ~= nil) -- false
-- The entry is removed from _GQuick Check
What is the scope of a variable declared with local x = 5 inside a for loop body?
Recap: Declaring Variables in Lua
Key takeaways from this lesson:
- Variables are global by default — always use
local - Locals are faster (no hash lookup) and safer
- Multiple assignment:
a, b = b, aswaps in one line - All globals live in
_G; setting tonildeletes them - Shadowing: inner
localhides outer variable without changing it - Use
UPPER_CASEfor constants by convention
Next: arithmetic, relational, and logical operators.
Frequently asked questions
Is the “Declaring Variables in Lua” lesson free?
Yes — the full text of “Declaring Variables in Lua” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Declaring Variables in Lua”?
Understand global vs local variables and naming conventions. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Declaring Variables in Lua” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Lua Data Types Overview
- Declaring Variables in Lua
- Arithmetic and Relational Operators
- Type Coercion and Conversion