如何为表中的函数设置名称

时间:2011-12-20 11:28:33

标签: lua lua-table

例如,我有一张表

table.insert( t, 1, function()
                        print ("rock");
                    end );

有没有办法从这个表中获取函数名称。我知道我可以像键一样存储名称,但如果我想保留数字索引并且我想知道函数名称怎么办? 有什么办法吗? 谢谢,提前。

4 个答案:

答案 0 :(得分:6)

说你有这段代码:

t = {}
x = 5
table.insert(t, 1, x)

t将为{[1] = 5}。 “5”只是一个数字 - 它没有名称,并且与变量“x”无关;这是一个 在Lua中,函数的处理方式与

完全相同
t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)

x的值不以任何方式,形状或形式与x相关联。如果要手动命名函数,可以将函数包装在表中,例如:

t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
    name = "MyFunctionName",
    func = x
})

你就是这样做的!

... 除非 ..

..你违反了规则!
当Lua开发出来时,开发人员意识到,如果不是不可能的话,函数的匿名性将使生产错误消息难以产生。
你会看到的最好的事情是:

stdin: some error!
  stdin: in function 'unknown'
  stdin: in function 'unknown'

因此,他们做到了这一点,当解析Lua代码时,它会记录一些 debug 信息,以使生活更轻松。要从Lua本身访问此信息,请提供debug library 要非常小心此库中的功能。

  

使用此库时应小心谨慎。此处提供的功能应专门用于调试和类似任务,例如分析。请抵制将它们用作通常的编程工具的诱惑:它们可能非常慢。此外,其中一些函数违反了一些关于Lua 代码的假设(例如,函数本地的变量无法从外部访问或者用户数据元表不能通过Lua代码更改)因此可能会损害其他安全性代码。

要达到理想的效果,您必须使用debug.getinfo功能;一个例子:

x = function()
    print("test!")
    print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"

不幸的是,直接在函数上运行的debug.getinfo形式没有填充name参数(debug.getinfo(x, "n").name == nil),上面的版本要求你运行该函数。
这似乎无望!

... 除非 ..

..你 真的 违反了规则 debug.sethook函数允许您在某些事件中中断运行的Lua代码,甚至在事情发生时更改内容。这与coroutines相结合,可以让你做一些有趣的hacky东西 以下是debug.getfuncname的实现:

function debug.getfuncname(f)
    --[[If name found, returns
            name source line
        If name not found, returns
            nil  source line
        If error, returns
            nil  nil    error
    ]]
    if type(f) == "function" then
        local info = debug.getinfo(f, "S")
        if not info or not info.what then
            return nil, nil, "Invalid function"
        elseif info.what == "C" then
            -- cannot be called on C functions, as they would execute!
            return nil, nil, "C function"
        end
        --[[Deep magic, look away!]]
        local co = coroutine.create(f)
        local name, source, linedefined
        debug.sethook(co, function(event, line)
            local info = debug.getinfo(2, "Sn")
            name = info.namewhat ~= "" and info.name or nil
            source, linedefined = info.short_src, info.linedefined
            coroutine.yield() -- prevent function from executing code
        end, "c")
        coroutine.resume(co)
        return name, source, linedefined
    end
    return nil, nil, "Not a function"
end

使用示例:

function test()
    print("If this prints, stuff went really wrong!")
end

print("Name = ", debug.getfuncname(test))

此功能不太可靠 - 它有时有效,而其他功能则无效。调试库非常敏感,所以可以预料到。

请注意,您应该从不将其用于实际的发布代码!仅用于调试!
仍然可以接受的最极端情况是记录已发布软件的错误,以帮助开发人员解决问题。 任何重要代码都不应该依赖于调试库中的函数。

祝你好运!

答案 1 :(得分:1)

该功能没有任何名称。如果需要,可以将其分配给命名变量:

theFunction = t[1]
-- Call it:
theFunction()

如果您想要将命名函数存储到表中,请事先定义它并使用其名称来存储它:

theFunction = function()
                  print ("rock");
              end

table.insert(t, 1, theFunction)

如果这不是您的意思,请提供更多详细信息;例如,您希望如何访问该功能。你的问题有点迷雾。

答案 2 :(得分:0)

事情是table.insert将表视为序列,仅使用数字键。

如果您希望能够将函数调用为t.fun(),则必须将该表用作关联数组,因此使用字符串作为键。 (BTW除了nil或NaN之外的任何类型都可以作为关键)

t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.

您可能还会注意到函数是通过引用传递的。因此,所有函数实际上都是匿名的,并且只是作为值存储到某个键或变量。

答案 3 :(得分:0)

您可以将名称存储在单独的表格中。

functions = {}
functionNames = {}

function addFunction(f, name)
  table.insert(functions, f)
  functionNames[name] = f
end

要获取该功能,您可以使用索引。获得该功能后,您可以从function_names获取其名称:

f = functions[3]
name = functionNames[f]
祝你好运!