Распечатать все локальные переменные, доступные для текущей области в Lua - PullRequest
27 голосов
/ 14 мая 2010

Я знаю, как напечатать «все» глобальные переменные, используя следующий код

for k,v in pairs(_G) do
    print("Global key", k, "value", v)
end

Поэтому мой вопрос заключается в том, как сделать это для всех переменных, доступных из выполняемой в данный момент функции, что может сделать то, что locals() делает для Python.

Ответы [ 5 ]

34 голосов
/ 14 мая 2010

Вот реализация функции locals(). Он вернет таблицу локальных пользователей из области вызова:

function locals()
  local variables = {}
  local idx = 1
  while true do
    local ln, lv = debug.getlocal(2, idx)
    if ln ~= nil then
      variables[ln] = lv
    else
      break
    end
    idx = 1 + idx
  end
  return variables
end

Обратите внимание, что в REPL lua каждая строка представляет собой отдельный кусок с отдельными местными жителями. Также возвращаются внутренние переменные (имена начинаются с '(', если вы хотите их удалить):

> local a = 2; for x, v in pairs(locals()) do print(x, v) end
a   2
(*temporary)    function: 0x10359b38

Спасибо за согласие. Вы открыли последний кусок головоломки! ; -)

Upvalues ​​- это локальные переменные из внешних областей, которые используются в текущей функции. Их нет ни в _G, ни в locals()

function upvalues()
  local variables = {}
  local idx = 1
  local func = debug.getinfo(2, "f").func
  while true do
    local ln, lv = debug.getupvalue(func, idx)
    if ln ~= nil then
      variables[ln] = lv
    else
      break
    end
    idx = 1 + idx
  end
  return variables
end

Пример (обратите внимание, вы должны использовать, чтобы он появился):

> local a= 2; function f() local b = a; for x,v in pairs(upvalues()) do print(x,v) end end; f()
a   2
6 голосов
/ 14 мая 2010

Использование debug.getlocal.

2 голосов
/ 25 июня 2012

Проблема с версией петли судьи Мейгардена выше local i = 0. Это ничего не делает, потому что первый индексированный с '0' всегда будет возвращать ноль.

Помните, что индексы Lua по умолчанию начинаются с '1', а не с '0', как C / C ++. Вы можете использовать '0' для индекса с вашими собственными типами, но функции по умолчанию ожидают значение по умолчанию '1' в качестве первого индекса.

Просто измените его на local i = 1, и его цикл будет работать нормально.

2 голосов
/ 14 мая 2010

См. debug.getlocal:

local foobar = 1

local i = 0
repeat
    local k, v = debug.getlocal(1, i)
    if k then
        print(k, v)
        i = i + 1
    end
until nil == k

Выход:

foobar  1
i       2
0 голосов
/ 14 мая 2010

Вы можете использовать getfenv для получения локальной среды.

getfenv ([f]) Возвращает текущий среда, используемая функцией. е может быть функцией Lua или числом, которое определяет функцию в этом стеке уровень: уровень 1 - это вызов функции getfenv. Если данная функция не функция Lua или, если f равно 0, getfenv возвращает глобальную среду. по умолчанию для f - 1.

Редактировать: извините, я ошибся.

Я только что проверил исходный код Lua. debug.getlocal() - единственный способ получить локальные переменные.
Lua использует внутреннюю структуру Proto и не дает нам доступа к ней.
(Proto содержит локальные свойства плюс родительскую ссылку на Proto. Итерация функции Proto с помощью getfenv,
мы также перебираем унаследованные свойства, а не то, что хотели)

Пользователи могут определять свои Proto с помощью сред и функций set/getfenv или с помощью метатаблиц.

...