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

发布于 2024-12-22 08:42:46 字数 225 浏览 2 评论 0原文

例如,我有一个表有

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

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

For example, I have a table

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

Is there any way to get function name from this table. I know that I can store name like a key, but what if I want to keep numeric index and also I want to know function name?
Is there any way to do it?
Thanks, on advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

痴者 2024-12-29 08:42:46

假设您有以下代码:

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
})

That's how you do it!

...除非..

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

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

所以,他们这样做是为了在解析 Lua 代码时,它会记录一些调试信息,以使生活更轻松。为了从 Lua 本身访问此信息,提供了调试库。< br>
使用此库中的函数时要非常小心。

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


为了达到你想要的效果,你必须使用调试。 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 代码,甚至可以在这一切发生时进行更改。这与协程相结合,可以让你做一些有趣的黑客事情。
以下是 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))

此函数不是很可靠 - 有时可以工作,但其他时候则不行。调试库非常敏感,所以这是可以预料的。

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

祝你好运!

Say you have this code:

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

t would then be {[1] = 5}. "5" is just a number - it has no name, and isn't associated with the variable "x"; it's a value.
In Lua, functions are treated exactly the same way, as values:

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

The value of x is not associated with x in any way, shape, or form. If you want to manually name a function, you can do it by wrapping the function in a table, for example:

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

That is how you would do it!

...unless..

..you break the rules!
When Lua was developed, the developers realised that the anonymous nature of functions would make productive error messages difficult to produce, if not impossible.
The best thing you'd see would be:

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

So, they made it so that when Lua code was parsed, it would record some debug information, to make life easier. To access this information from Lua itself, the debug library is provided.
Be very careful with functions in this library.

You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.

To achieve your desired effect, you must use the debug.getinfo function; an example:

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

Unfortunately, the form of debug.getinfo that operates directly on a function doesn't fill the name argument (debug.getinfo(x, "n").name == nil) and the version above requires you to run the function.
It seems hopeless!

...unless..

..you really break the rules.
The debug.sethook function allows you to interrupt running Lua code at certain events, and even change things while it's all happening. This, combined with coroutines, allows you to do some interestingly hacky stuff.
Here is an implementation of 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

Example usage:

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

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

This function isn't very reliable - it works sometimes, and doesn't others. The debug library is very touchy, so it's to be expected.

Note that you should never use this for actual release code! Only for debugging!
The most extreme case that is still acceptable is logging errors on piece of released software, to help the developer fix issues. No vital code should depend on functions from the debug library.

Good luck!

梦归所梦 2024-12-29 08:42:46

该函数没有任何名称。如果您愿意,可以将其分配给命名变量:

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

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

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

table.insert(t, 1, theFunction)

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

The function hasn't got any name. If you want you can assign it to a named variable:

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

If what you want is storing a named function to the table, define it beforehand and use its name to store it:

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

table.insert(t, 1, theFunction)

If this is not what you meant, give more details; for example how you would like to access the function. You're question is a bit misty.

_失温 2024-12-29 08:42:46

问题是 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.

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

The thing is table.insert considers the table as a sequence, only with numeric keys.

If you want to be able to call the function as t.fun() you'll have to use the table as an associative array and hence use a string as key. (BTW any type except nil or NaN are allowed as key)

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

You might also notice that functions are passed by reference. So all functions are actually anonymous, and are just stored as a value to a certain key or variable.

佼人 2024-12-29 08:42:46

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

functions = {}
functionNames = {}

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

要获取该函数,可以使用索引。一旦你有了这个函数,你就可以从 function_names 中得到它的名字:

f = functions[3]
name = functionNames[f]

祝你好运!

You can store the names in a separate table.

functions = {}
functionNames = {}

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

To get the function, you can use the index. Once you have the function, you can get its name from function_names:

f = functions[3]
name = functionNames[f]

Good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文