在Lua中,处理包含nil的varargs的正确方法是什么?

时间:2011-08-25 00:58:15

标签: lua

我正在尝试创建一个调试打印函数,它将文件句柄作为第一个参数。首先,我写一个这样的函数:

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

那么,解决这个问题的正确方法是什么?

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会更容易。