3

当调用像这样的lua函数时

PrintMe(我的变量名)

我希望能够实际打印“MyVariableName”而不是它的值(嗯,用于演示目的)。

显然我可以只传递字符串,但这需要额外的引号,我也想打印它的值。

例如,

MyVariable = 4
PrintVariable(MyVariable)

将打印“MyVariable is 4”或其他

我不想重复名称和变量,例如

PrintVariable(MyVariable, "MyVariable")

因为这是不必要的重复。

lua可以处理吗?

我现在正在做的是在引号中传递变量名并使用 loadstring 来获取值,但我想直接传递变量而不需要额外的不必要的引号(我认为 debug.getlocal 做了但它最终返回了值而不是名称)。


这是模拟示例

function printme1(var, val)
    print(var.." = "..val)
end

function printme2(v)
    local r
    loadstring("r = "..v)() -- equivalent to r = a but must be used since v is a string representing a and not the object a
    print(v.." = "..tostring(r))
end

function printme3(v)
    -- unknown
end

a = 3

printme1("a", a)
printme2("a")
printme3(a) 

在这种情况下,所有 3 都应该打印相同的东西。printme3 显然是最方便的。

4

6 回答 6

5

您不能说PrintVariable(MyVariable),因为 Lua 无法确定使用哪个变量(如果有的话;可以使用常量)将参数传递给您的函数。但是,您可以PrintVariable('MyVariable')然后使用调试 API 在调用者的范围内查找具有该名称的局部变量:

function PrintVariable(name)
  -- default to showing the global with that name, if any
  local value = _G[name]

  -- see if we can find a local in the caller's scope with that name
  for i=1,math.huge do
    local localname, localvalue = debug.getlocal(2,i,1)
    if not localname then
      break -- no more locals to check
    elseif localname == name then
      value = localvalue
    end
  end

  if value then
    print(string.format("%s = %s", name, tostring(value)))
  else
    print(string.format("No variable named '%s' found.", name))
  end
end

现在你可以说:

PrintVariable('MyVariable')

而在这种情况下将打印“MyVariable = 4”。


不,如果您真的想在没有引号的情况下执行此操作,您可以检查调用者的本地变量是否具有提供的值,但如果调用者的范围内有多个变量,这有时会给您错误的变量名称给定的值。话虽如此,您可以这样做:

function PrintVariable(value)
  local name

  -- see if we can find a local in the caller's scope with the given value
  for i=1,math.huge do
    local localname, localvalue = debug.getlocal(2,i,1)
    if not localname then
      break
    elseif localvalue == value then
      name = localname
    end
  end

  -- if we couldn't find a local, check globals
  if not name then
    for globalname, globalvalue in pairs(_G) do
      if globalvalue == value then
        name = globalname
      end
    end
  end

  if name then
    print(string.format("%s = %s", name, tostring(value)))
  else
    print(string.format("No variable found for the value '%s'.", tostring(value)))
  end
end

现在你可以说PrintVariable(MyVariable),但是如果在调用者的作用域中碰巧有另一个具有 value 的变量4,并且它发生在之前MyVariable,那么将打印那个变量名。

于 2012-05-05T05:24:10.613 回答
0

我有个坏消息,我的朋友。您可以访问出现在函数顶部的函数参数名称,但不存在用于准确访问它们在调用函数中命名的数据。请参阅以下内容:

function PrintVariable(VariableToPrint)
  --we can use debug.getinfo() to determine the name 'VariableToPrint'
  --we cannot determine the name 'MyVariable' without some really convoluted stuff (see comment by VBRonPaulFan on his own answer)
  print(VariableToPrint);
end

MyVariable = 4
PrintVariable(MyVariable)

为了说明这一点,想象一下如果我们这样做了:

x = 4
MyVariable = x
MyOtherVariable = x
x = nil

PrintVariable(MyVariable)

现在,如果你是 Lua,你会在元数据中为最终传递给函数的变量附加什么名称?是的,您可以使用 debug.getint() 向上查找传入的变量,但您可能会找到几个引用。还要考虑:

PrintVariable("StringLiteral")

你会怎么称呼那个变量?它有一个值但没有名称。

于 2012-05-05T04:01:14.930 回答
0

你可以用调试库做这样的事情......这样的事情你似乎正在寻找:

function a_func(arg1, asdf)
    -- if this function doesn't use an argument... it shows up as (*temporary) in 
    -- calls to debug.getlocal() because they aren't used...
    if arg1 == "10" then end
    if asdf == 99 then end
    -- does stuff with arg1 and asdf?
end

-- just a function to dump variables in a user-readable format
function myUnpack(tbl)
    if type(tbl) ~= "table" then
        return ""
    end

    local ret = ""
    for k,v in pairs(tbl) do
        if tostring(v) ~= "" then
            ret = ret.. tostring(k).. "=".. tostring(v).. ", "
        end
    end
    return string.gsub(ret, ", $", "")
end

function hook()
    -- passing 2 to to debug.getinfo means 'give me info on the function that spawned 
    -- this call to this function'. level 1 is the C function that called the hook.
    local info = debug.getinfo(2)
    if info ~= nil and info.what == "Lua" then
        local i, variables = 1, {""}
        -- now run through all the local variables at this level of the lua stack
        while true do
            local name, value = debug.getlocal(2, i)
            if name == nil then
                break
            end
            -- this just skips unused variables
            if name ~= "(*temporary)" then
                variables[tostring(name)] = value
            end
            i = i + 1
        end
            -- this is what dumps info about a function thats been called
        print((info.name or "unknown").. "(".. myUnpack(variables).. ")")
    end
end

-- tell the debug library to call lua function 'hook 'every time a function call
-- is made...
debug.sethook(hook, "c")

-- call a function to try it out...
a_func("some string", 2012)

这导致输出:

a_func(asdf=2012, arg1=some string)

你可以做一些更漂亮的东西来美化它,但这基本上涵盖了如何做你所要求的。

于 2012-05-05T04:40:58.093 回答
0

你可以使用这种形式:

local parms = { "MyVariable" }

local function PrintVariable(vars)
   print(parms[1]..": "..vars[1])
end

local MyVariable = "bar"

PrintVariable{MyVariable}

这使:

MyVariable: bar

它不是通用的,但很简单。您可以通过这种方式避免调试库和加载字符串。如果你的编辑器不错,你可以写一个宏来做。

于 2012-05-05T12:47:30.640 回答
0

另一种可能的解决方案是您自己添加此设施。Lua C API 和源代码非常简单且可扩展。

我/我们不知道您的项目/工作的背景,但如果您正在制作/嵌入自己的 Lua 构建,您可以扩展debug库以执行此操作。

Lua 通过引用传递它的值,但不知道这些值是否包含字符串名称以及是否易于访问。

在您的示例中,值声明与以下内容相同:

_G["MyVariable"] = 4

因为它是全球性的。如果它被声明了,local那么就像这里所说的其他人一样,您可以通过debug.getlocal(). 但同样在实际引用上下文的 C 上下文中,它可能并不重要。

实现一个debug.getargumentinfo(...)使用名称键值对扩展参数表的 a。

于 2012-06-25T00:57:21.963 回答
0

这是一个相当古老的话题,我很抱歉让它重新焕发生机。

根据我使用 lua 的经验,我所知道的最接近 OP 要求的是这样的:

PrintVariable = {}
setmetatable(PrintVariable, {__index = function (self, k, v) return string.format('%s = %s', k, _G[k]) end})

VAR = 0
VAR2 = "Hello World"

print(PrintVariable.VAR, PrintVariable.VAR2)
-- Result: VAR = 0  VAR2 = Hello World

我不做更多解释,因为代码可读性很强,但是:这里发生的事情很简单,您只需为PrintVariable变量设置一个元表并添加__index当表被迫在其索引中搜索值时调用的元方法,多亏了这个功能,您可以实现您在示例中看到的内容。

参考:https ://www.lua.org/manual/5.1/manual.html

我希望未来和新的访问者会发现这很有帮助。

于 2021-02-15T10:14:05.893 回答