0Pricing
Lua Academy · Lesson

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)) -- 100

select() 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  d

Passing ... 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.lua

table.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  30

Mixed 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  z

Vararg 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.0

Quick Check

What does select("#", 1, nil, 3) return?

Recap: Varargs

Summary:

  • function f(...) — accepts variable arguments
  • select("#", ...) — safe count including nils
  • select(n, ...) — values from position n
  • table.pack(...) — varargs to table with .n count
  • table.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

  1. Defining and Calling Functions
  2. Multiple Return Values
  3. Varargs and the ... Operator
  4. Recursion in Lua
← Back to Lua Academy