我正在尝试创建一个调试打印函数,它将文件句柄作为第一个参数。首先,我写一个这样的函数:
function fprint (f, ...)
for i, v in ipairs{...} do
f:write(tostring(v))
f:write("\t")
end
f:write("\n")
end
只要我没有在参数中传递nil
值,此函数就会起作用。但是,如果我用nil
调用它,它不会打印nil
值和其余参数。
fprint(io.stderr, 1, 2, nil, 3)
=> prints only 1 and 2
那么,解决这个问题的正确方法是什么?
答案 0 :(得分:28)
实际上,在varargs中处理nil
值很容易,你只需要使用select
函数,它甚至可以用nil
(它计算参数的实际数量) 。以下习语非常有用,它是Lua 5.2中的核心库函数table.pack
:
function table.pack(...)
return { n = select("#", ...), ... }
end
参数的数量存储在字段n
中,因此为了迭代它们,只需使用它:
function vararg(...)
local args = table.pack(...)
for i=1,args.n do
-- do something with args[i], careful, it might be nil!
end
end
答案 1 :(得分:2)
据我所知,没有简单的实现独立方式来了解包含nil
条目的数组的长度,因为#
操作可以指向任何后跟{{1}的位置但是,这是一个快速实现相关的解决方案,将打印nil
。
nil
而不是在function fprint (f, ...)
local parm={...}
for i=1,#parm do
f:write(tostring(parm[i]))
f:write("\t")
end
f:write("\n")
end
上转发,你可以变得复杂(因此独立于实现),因为你知道#
表是一个数组并使用这样的东西:
parm
如果您可以跳过function last_index(array)
local max = 0
for k, _ in pairs(array) do
max = math.max(max, k)
end
return max
end
function fprint (f, ...)
local parm={...}
for i=1,last_index(parm) do
f:write(tostring(parm[i]))
f:write("\t")
end
f:write("\n")
end
值且订单不重要,那么切换到nil
会更容易。