Varargs and the ... Operator
Handle variable-length argument lists using ... and select().
Varargs and the ... Operator is a free Lua Academy lesson on CoddyKit — lesson 3 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.
Variable Arguments
A Lua function can accept a variable number of arguments using ... (three dots) in the parameter list. Inside the function, ... represents the extra arguments. You can use it in expressions, pass it to other functions, or convert it to a table.
local function sum(...)
local total = 0
for _, v in ipairs({...}) do
total = total + v
end
return total
end
print(sum(1, 2, 3)) -- 6
print(sum(10, 20, 30, 40)) -- 100select() for Varargs
select(n, ...) returns arguments from position n onward. select("#", ...) returns the total count of arguments including nil values. This is safer than #{...} which stops at the first nil hole.
local function inspect(...)
local n = select("#", ...)
print("count:", n)
for i = 1, n do
print(i, select(i, ...))
end
end
inspect("a", "b", nil, "d")
-- count: 4
-- 1 a
-- 2 b
-- 3 nil
-- 4 dPassing ... to Another Function
You can forward varargs directly to another function with f(...). When ... appears as the last argument in a call, all the variable arguments are passed. This is useful for wrapping functions or logging.
local function log(level, ...)
io.write("[" .. level .. "] ")
print(...)
end
log("INFO", "Server started on port", 8080)
log("ERROR", "File not found:", "config.lua")
-- [INFO] Server started on port 8080
-- [ERROR] File not found: config.luatable.pack and table.unpack
Convert varargs to a table with table.pack(...), which also stores the count in field n. Convert a table back to varargs with table.unpack(t, i, j). Together, these functions give you full control over variable argument lists.
local function pack_and_show(...)
local packed = table.pack(...)
print("n =", packed.n)
for i = 1, packed.n do
print(i, packed[i])
end
end
pack_and_show(10, nil, 30)
-- n = 3
-- 1 10
-- 2 nil
-- 3 30Mixed Fixed and Variable Args
A function can have both fixed and variable parameters. Fixed parameters come first; ... captures the rest. The fixed parameters are assigned before the rest go into ....
local function printf(fmt, ...)
io.write(string.format(fmt, ...))
end
printf("Hello, %s! You are %d years old.\n", "Alice", 30)
printf("Pi is approximately %.4f\n", math.pi)
local function firstAndRest(first, ...)
print("first:", first)
print("rest count:", select("#", ...))
end
firstAndRest(1, 2, 3, 4)Varargs in Table Constructor
You can splat varargs directly into a table constructor: {...}. When used as the last element, all args are included. However, nil holes may confuse # — prefer table.pack when you need exact counts.
local function toArray(...)
return {...} -- collect all args as array
end
local arr = toArray("x", "y", "z")
for i, v in ipairs(arr) do
print(i, v)
end
-- 1 x
-- 2 y
-- 3 zVararg Expressions
... can appear in any expression position. In a multiple assignment, it expands to all its values. In an arithmetic expression, only the first value is used. Understanding this behavior prevents subtle bugs when mixing ... with other expressions.
local function first(...)
local x = ...
return x
end
print(first(10, 20, 30)) -- 10 (only first)
local function addFirst(n, ...)
local x = ...
return n + x
end
print(addFirst(5, 3, 99)) -- 8 (3 is first ...)print() Uses Varargs
Lua's built-in print() is itself a vararg function. It accepts any number of arguments, converts each to a string, and separates them with tabs. Understanding this helps you write similar utility functions.
-- print is vararg
print(1, 2, 3) -- 1 2 3
print("a", nil, "b") -- a nil b
print() -- (empty line)
-- Reimplementing a simple print-like function
local function myprint(...)
local parts = {}
for i = 1, select("#", ...) do
parts[i] = tostring(select(i, ...))
end
io.write(table.concat(parts, "\t") .. "\n")
end
myprint(10, nil, 30)Forwarding with pcall
Combine pcall with varargs to create a generic safe-call wrapper. The wrapper accepts a function and any arguments, calls it via pcall, and returns the results or an error.
local function safeCall(fn, ...)
local ok, result = pcall(fn, ...)
if ok then
return result
else
print("Error:", result)
return nil
end
end
local function divide(a, b)
assert(b ~= 0, "division by zero")
return a / b
end
print(safeCall(divide, 10, 2)) -- 5.0
print(safeCall(divide, 10, 0)) -- Error: ...Accumulate Varargs Pattern
A common vararg pattern is to iterate over all arguments and accumulate a result. This can be done with a local table or by directly summing with select. Both approaches are valid; the table approach is cleaner for many arguments.
local function average(...)
local n = select("#", ...)
if n == 0 then return 0 end
local total = 0
for i = 1, n do
total = total + select(i, ...)
end
return total / n
end
print(average(10, 20, 30, 40)) -- 25.0
print(average(5)) -- 5.0Quick Check
What does select("#", 1, nil, 3) return?
Recap: Varargs
Summary:
function f(...)— accepts variable argumentsselect("#", ...)— safe count including nilsselect(n, ...)— values from position ntable.pack(...)— varargs to table with .n counttable.unpack(t)— table to varargs...in last position expands fully; middle position gives one value
Frequently asked questions
Is the “Varargs and the ... Operator” lesson free?
Yes — the full text of “Varargs and the ... Operator” 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 “Varargs and the ... Operator”?
Handle variable-length argument lists using ... and select(). 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 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Varargs and the ... Operator” 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
- Defining and Calling Functions
- Multiple Return Values
- Varargs and the ... Operator
- Recursion in Lua