В Lua, как правильно обрабатывать переменные, содержащие ноль? - PullRequest
20 голосов
/ 25 августа 2011

Я пытаюсь создать функцию отладочной печати, которая принимает дескриптор файла в качестве первого аргумента.Во-первых, я пишу такую ​​функцию:

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 ]

28 голосов
/ 25 августа 2011

На самом деле, легко обрабатывать значения 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 голосов
/ 25 августа 2011

Насколько я знаю, не существует простого способа, независимого от реализации, чтобы узнать длину массива, содержащего 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 будет намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...