例如,我有一张桌子
table.insert( t, 1, function()
print ("rock");
end );
有没有办法从这个表中获取函数名。我知道我可以像键一样存储名称,但是如果我想保留数字索引并且还想知道函数名称怎么办?有什么办法吗?谢谢,提前。
假设您有以下代码:
t = {}
x = 5
table.insert(t, 1, x)
t
那么将是{[1] = 5}
. “5”只是一个数字——它没有名字,并且与变量“x”无关;这是一个值。在 Lua 中,函数的处理方式与values
完全相同:
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 代码被解析时,它会记录一些调试信息,让生活更轻松。为了从 Lua 本身访问这些信息,提供了调试库。
对这个库中的函数要非常小心。
使用此库时应小心。此处提供的功能应专门用于调试和类似任务,例如分析。请抵制将它们用作常用编程工具的诱惑:它们可能非常慢。此外,其中一些函数违反了一些关于 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))
这个功能不是很可靠——它有时有效,而其他时候无效。调试库非常敏感,所以这是意料之中的。
请注意,您永远不应该将它用于实际的发布代码!仅用于调试!
仍然可以接受的最极端情况是在已发布软件上记录错误,以帮助开发人员解决问题。任何重要的代码都不应该依赖于调试库中的函数。
祝你好运!
该函数没有任何名称。如果需要,可以将其分配给命名变量:
theFunction = t[1]
-- Call it:
theFunction()
如果您想要将命名函数存储到表中,请预先定义它并使用其名称来存储它:
theFunction = function()
print ("rock");
end
table.insert(t, 1, theFunction)
如果这不是您的意思,请提供更多详细信息;例如,您希望如何访问该功能。你的问题有点模糊。
您可以将名称存储在单独的表中。
functions = {}
functionNames = {}
function addFunction(f, name)
table.insert(functions, f)
functionNames[name] = f
end
要获取函数,可以使用索引。一旦你有了这个函数,你可以从 function_names 中得到它的名字:
f = functions[3]
name = functionNames[f]
祝你好运!
事情是 table.insert 将表格视为一个序列,只有数字键。
如果您希望能够调用该函数,t.fun()
则必须将表用作关联数组,因此使用字符串作为键。(顺便说一句,除了 nil 或 NaN 之外的任何类型都可以作为键)
t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.
您可能还注意到函数是通过引用传递的。因此,所有函数实际上都是匿名的,并且只是作为某个键或变量的值存储。