在Lua中,是否有一个函数给定一个函数,它以字符串形式返回其名称?

在Lua中,是否有一个函数给定一个函数,它以字符串形式返回其名称?,lua,Lua,抱歉,如果这太明显了,但我是lua的新手,在参考资料中找不到 在Lua中有函数的名称吗?给定一个函数给我它的名字,这样我就可以用它索引一个表了?我想这样做的原因是我想做这样的事情: local M = {} local function export(...) for x in ... M[NAME_OF_FUNCTION(x)] = x end end local function fun1(...) ... end local function fun2(...)

抱歉,如果这太明显了,但我是lua的新手,在参考资料中找不到

在Lua中有函数的名称吗?给定一个函数给我它的名字,这样我就可以用它索引一个表了?我想这样做的原因是我想做这样的事情:

local M = {}

local function export(...)
   for x in ...
     M[NAME_OF_FUNCTION(x)] = x
   end
end

local function fun1(...)
...
end

local function fun2(...)
...
end

.
.
.

export(fun1, fun2, ...)

return M
fun1={
    fun=function(self,...)
        print("Hello from "..self.name)
        print("Arguments received:")
        for k,v in pairs{...} do print(k,v) end
    end,
    name="fun1"
}
fun_mt={
    __call=function(t,...)
        t.fun(t,...)
    end,
    __tostring=function(t)
        return t.name
    end
}
setmetatable(fun1,fun_mt)
fun1('foo')
print(fun1) -- or print(tostring(fun1))
试试这个:

如果我没有错的话,tostring(x)应该是您想要的(我可能会,因为我实际上从未用Lua编程,只是读过一堆论文和文章),在内部已经有一个带有函数名的表(比如Python中的
locals
globals
),因此,您应该能够执行反向查找,以查看哪个键与函数引用匹配

总之,只是猜测而已


但事实是,查看代码时,您已经知道函数的名称,因此可以自由构造表。如果您想减少出错的可能性,那么使用函数名来获取函数引用(使用
eval
或类似的方法)比使用其他方法更容易。

根本没有这样的函数。我想没有这样的功能,因为功能是一等公民。所以一个函数和其他任何函数一样,都是一个被变量引用的值。因此,函数的
名称\u
不是很有用,因为同一个函数可能有许多变量指向它,或者没有变量指向它

您可以通过在表中循环(任意或_G),检查值是否等于x来模拟全局函数或表中的函数。如果是这样,您已经找到了函数名

a=function() print"fun a" end
b=function() print"fun b" end
t={
   a=a,
   c=b
}
function NameOfFunctionIn(fun,t) --returns the name of a function pointed to by fun in table t
   for k,v in pairs(t) do
       if v==fun then return k end
   end
end
print(NameOfFunctionIn(a,t)) -- prints a, in t
print(NameOfFunctionIn(b,t)) -- prints c
print(NameOfFunctionIn(b,_G)) -- prints b, because b in the global table is b. Kind of a NOOP here really.
另一种方法是将函数包装到表中,并设置一个调用该函数的元表,如下所示:

local M = {}

local function export(...)
   for x in ...
     M[NAME_OF_FUNCTION(x)] = x
   end
end

local function fun1(...)
...
end

local function fun2(...)
...
end

.
.
.

export(fun1, fun2, ...)

return M
fun1={
    fun=function(self,...)
        print("Hello from "..self.name)
        print("Arguments received:")
        for k,v in pairs{...} do print(k,v) end
    end,
    name="fun1"
}
fun_mt={
    __call=function(t,...)
        t.fun(t,...)
    end,
    __tostring=function(t)
        return t.name
    end
}
setmetatable(fun1,fun_mt)
fun1('foo')
print(fun1) -- or print(tostring(fun1))

由于元表查找,这将比使用裸函数慢一点。它不会阻止任何人更改状态中函数的名称、更改包含它的表中函数的名称、更改函数等,因此它不是防篡改的。您还可以通过像
fun1.fun
这样的索引来剥离表,如果您将其作为模块导出,这可能会很好,但是您会失去可以放入元表中的命名和其他技巧。

从技术上讲,这是可能的,下面是export()函数的一个实现:

function export(...)
        local env = getfenv(2);
        local funcs = {...};
        for i=1, select("#", ...) do
                local func = funcs[i];
                for local_index = 1, math.huge do
                        local local_name, local_value = debug.getlocal(2, local_index);
                        if not local_name then
                                break;
                        end
                        if local_value == func then
                                env[local_name] = local_value;
                                break;
                        end
                end
        end
        return env;
end

它使用了,需要对Lua5.2进行一些更改,最后我不一定认可它是编写模块的好方法,我只是简单地回答了这个问题。

我怀疑这是否有效,所以我尝试了它,但它似乎没有:哦,我承认我有点冒昧:(string.format也不起作用。似乎没有任何合适的格式选项……这里有一个类似的SO线程:这表明没有很好的解决方案。我可以将字符串传递给导出自己,但我想我会问,因为我认为传递func本身更优雅。尽管这太困难了,从那以后就没有了。)源代码中的名称只存在于源代码中。我认为您在这一点上弄错了源代码中的名称只存在于源代码中。这对于大多数静态语言和编译语言来说都是正确的,但是动态/脚本语言通过查找其名称来分派函数,因此它们可以进行后期绑定(并允许将函数重新绑定到monkey修补程序代码等)虽然我同意原来的问题和意图可能是重复的,但幸运的是,这两个问题的答案并不重复,反而在我看来是互补的。我有一次在两条线索中发现了一条线索中的信息,而另一条线索中没有。我不知道它们是否可以以某种方式合并。你是对的说到它,我能找到的最接近的东西是debug.getinfo函数。但它不返回名称。而且全局表也没有提到本地函数。我仍在寻找一种内省方法,从对象获取名称,或者像你说的,从名称获取对象。但目前为止运气不好。关于函数是一个值,但这并不意味着它不能是一个复合值,将函数的代码和名称作为与其关联的元数据。我理解这只是Lua方式:定义的每个函数都只是一个lambda,存储在一个表中,表中的键为函数定义的名称:“语句函数f()根据Lua referencetrue,body end转换为f=function()body end“,但该键不必是字符串。在Lua中,以下内容完全正确:
t={[function()print'foo'end]=function()print'bar'end,{}=function()print'baz'end}
这里的键分别是函数和表。也就是说,表包含函数,而不是相反。您可以将元数据附加到函数,但它始终是“外部,如我给出的示例中所示。在Lua中,函数不是复合值,它只是函数,这符合Lua处理工具的哲学,允许构建任何真实的东西,我没有更多的补充:)