可变参数和 ... 运算符
使用 ... 和 select() 处理长度可变的参数列表。
可变参数和 ... 运算符 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。
可变参数
Lua 函数可以在参数列表中使用 ...(三个点)来接收数量可变的参数。在函数内部,... 表示额外参数。您可以在表达式中使用它,将其传递给其他函数,或将其转换为表。
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() 处理可变参数
select(n, ...) 会返回从第 n 个位置开始的所有参数。select("#", ...) 会返回参数总数,包括 nil 值。这比遇到第一个 nil 空缺就停止的 #{...} 更安全。
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将 ... 传递给另一个函数
您可以使用 f(...) 将可变参数直接转发给另一个函数。当 ... 出现在调用的最后一个参数位置时,所有可变参数都会被传递。这对于包装函数或记录日志非常有用。
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 和 table.unpack
使用 table.pack(...) 可以将可变参数转换为表,同时将数量存储在字段 n 中。使用 table.unpack(t, i, j) 可以将表转换回可变参数。这两个函数结合使用,可以让您完全控制可变参数列表。
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固定参数与可变参数混用
一个函数可以同时包含固定参数和可变参数。固定参数位于前面;... 捕获其余参数。固定参数会先被赋值,然后剩余参数才会进入 ...。
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)表构造器中的可变参数
您可以使用 {...} 将可变参数直接展开到表构造器中。当它用作最后一个元素时,所有参数都会被包含。不过,nil 空缺可能会导致 # 的结果不可靠——需要精确计数时,请优先使用 table.pack。
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可变参数表达式
... 可以出现在任何表达式位置。在多重赋值中,它会展开为所有值。在算术表达式中,只会使用第一个值。了解这一行为,可以避免将 ... 与其他表达式混用时出现隐蔽错误。
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() 使用可变参数
Lua 内置的 print() 本身就是一个可变参数函数。它可以接收任意数量的参数,将每个参数转换为字符串,并用制表符分隔它们。了解这一点有助于您编写类似的实用函数。
-- 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)使用 pcall 转发参数
将 pcall 与可变参数结合,可以创建通用的安全调用包装器。该包装器接收一个函数和任意数量的参数,通过 pcall 调用该函数,并返回结果或错误。
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: ...累积可变参数模式
一种常见的可变参数模式是遍历所有参数并累积结果。您可以使用局部表来完成,也可以通过 select 直接求和。两种方式都有效;对于参数较多的情况,使用表的方式更简洁。
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快速检查
select("#", 1, nil, 3) 会返回什么?
回顾:可变参数
总结:
function f(...)— 接受可变参数select("#", ...)— 安全地计数,包括 nil 值select(n, ...)— 返回从第 n 个位置开始的值table.pack(...)— 将可变参数转换为带有 .n 计数的表table.unpack(t)— 将表转换为可变参数...位于最后一个位置时会完整展开;位于中间位置时只产生一个值
常见问题解答
「可变参数和 ... 运算符」课时是免费的吗?
是的 — 「可变参数和 ... 运算符」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。
「可变参数和 ... 运算符」这节课中我会学到什么?
使用 ... 和 select() 处理长度可变的参数列表。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Lua Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「可变参数和 ... 运算符」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Lua Academy 课中编写并运行代码吗?
能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。