5

这里是 Lua 新手。我可以将函数引用作为键存储在 Lua 表中吗?与此类似的东西:

local fn = function() print('hello') end
local my_table = {}
my_table[fn] = 123

这似乎工作正常,但我不知道我是否可以依赖函数引用的唯一性。一旦超出范围,Lua 可以重用函数引用吗?这会产生任何问题还是由于某种原因被认为是一种不好的做法?

4

4 回答 4

6

是的。我在 lua 中遇到的最好的事情之一就是任何作为引用的属性。

key您在表格中使用 s 的方式没有任何问题。

来自Lua PiL

Lua 中的表既不是值也不是变量。它们是对象。您可以将表视为动态分配的对象;您的程序仅操作对它们的引用(或指针)。在幕后没有隐藏的副本或新表的创建。

在您的示例中,您没有将任何参数传递给函数,所以基本上,在您的情况下,将函数作为程序中的引用是没有用的。另一方面,是这样的:

fn1 = function(x) print(x) end
fn2 = function(x) print("bar") end
t[fn1] = "foo"
t[fn2] = "foo"
for i, v in pairs(t) do i(v) end

确实有它的用途。

一旦超出范围,Lua 可以重用函数引用吗?

只要您的父表在范围内,就可以。由于表是创建和操作的,但不是复制的,因此不可能从表索引内存中弃用您的函数引用。我也会在实际尝试后编辑这个答案。

这会产生任何问题还是由于某种原因被认为是一种不好的做法?

这只是一种不好的做法,因为熟悉其他语言的用户,如Cpython。在阅读表格时往往会考虑数组。在中你没有这样的担心,程序会完美运行。

我不知道我是否可以依赖函数引用的唯一性。

为什么?

于 2013-01-28T14:22:06.153 回答
3

函数引用的唯一性取决于 Lua 版本。

Lua 5.2手册说:
a function definition may not create a new value; it may reuse some previous value if there is no observable difference to the new function

例子:

-- 10 different function references on Lua 5.1
-- The same function reference for Lua 5.2
local j
for i = 1, 10 do
   print(function() print(j) end)
end

-- 10 different function references for any Lua version
for i = 1, 10 do
   print(function() print(i) end)
end

所以,规则是:创建不同的闭包来获得不同的引用。

于 2013-01-29T00:32:59.027 回答
1

您可以这样做,function将保留在内存的同一位置,直到它被销毁(由垃圾收集器)。

您可以尝试交互式lua

> fn = function() print('hello') end
> print(fn)
function: 0x9d058d0

> fn2 = function() print('hello') end
> print(fn2)
function: 0x9d05ee8

> fn2=fn
> print(fn2)
function: 0x9d058d0

> print(function() print('hello') end)
function: 0x9d068a8

> print(function() print('hello') end)
function: 0x9d06bf8

请记住,如果超出范围,它将被垃圾收集fnlocal在你的情况下,它不应该my_tablelocal同一个块中的问题。请参阅有关局部变量的 Lua 文档

于 2013-01-28T14:23:43.523 回答
1

这似乎工作正常,但我不知道我是否可以依赖函数引用的唯一性。

每个function() end语句都会创建一个新的闭包。如果函数的实际代码来自同一个构造函数,它将被重用:

for i=1,100 do
    t[function() print(i) end] = i -- this function body will be reused
end

但是每个闭包都是独一无二的,这对您的参考很重要。

一旦超出范围,Lua 可以重用函数引用吗?

Lua 是不会收集fn的,只要它被用作my_table. 如果my_table超出范围,使得表和函数都被收集,那么 Lua 重用引用不会影响你。所以无论哪种方式,你都很好。

于 2013-01-28T17:53:15.250 回答