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

unr*_*nal 1 lua lua-table

例如,我有一张桌子

table.insert( t, 1, function()
                        print ("rock");
                    end );
Run Code Online (Sandbox Code Playgroud)

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

Dec*_*eco 6

说你有这个代码:

t = {}
x = 5
table.insert(t, 1, x)
Run Code Online (Sandbox Code Playgroud)

t那会是{[1] = 5}."5"只是一个数字 - 它没有名称,并且与变量"x"无关; 这是一个价值.
在Lua中,函数的处理方式与完全相同:

t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)
Run Code Online (Sandbox Code Playgroud)

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

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

你就是这样做的!

...... 除非 ......

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

stdin: some error!
  stdin: in function 'unknown'
  stdin: in function 'unknown'
Run Code Online (Sandbox Code Playgroud)

因此,他们这样做,以便在解析Lua代码时,它会记录一些调试信息,以使生活更轻松.要从Lua本身访问此信息,请提供调试库.
对此库中的函数要非常小心.

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

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

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

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

...... 除非 ......

..你真的违反了规则.
debug.sethook函数允许您在某些事件中中断运行的Lua代码,甚至在事情发生时更改内容.这与协同程序相结合,可以让你做一些有趣的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
Run Code Online (Sandbox Code Playgroud)

用法示例:

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

print("Name = ", debug.getfuncname(test))
Run Code Online (Sandbox Code Playgroud)

这个功能不是很可靠 - 它有时可以工作,而不是其他功能.调试库非常敏感,所以可以预料到.

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

祝好运!