В Lua, каков правильный способ обработки varargs, который содержит nil?
Я пытаюсь создать функцию отладки печати, которая принимает дескриптор файла в качестве первого аргумента. Во-первых, я пишу такую функцию:
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
Итак, как правильно решить эту проблему?
Ответы
Ответ 1
На самом деле, легко обрабатывать значения nil
в varargs, все, что вам нужно, это использовать функцию select
, которая работает даже с nil
(он подсчитывает фактическое количество параметров). Следующая идиома настолько полезна, что она является основной библиотечной функцией table.pack
в Lua 5.2:
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
Ответ 2
Насколько я знаю, нет простого независимого способа реализации длины массива, содержащего записи nil
, поскольку операция #
может указывать на любую позицию, за которой следует 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
, и порядок не важен, то переход на pairs
будет намного проще.