lua函数引用可以用作表键吗?

时间:2013-01-28 14:05:24

标签: function reference lua key lua-table

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

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

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

4 个答案:

答案 0 :(得分:6)

呀。我在lua遇到的最好的事情之一是任何作为参考属性。

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

来自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等,在阅读表时往往会考虑数组。在你没有这样的担忧,程序将完美无缺。

  
    

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

  

为什么?

答案 1 :(得分: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

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

答案 2 :(得分: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_table在同一个块中是local。请参阅Lua documentation on local variables

答案 3 :(得分:1)

  

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

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

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

但是每个闭包都是唯一的,这对您的参考非常重要。

  

Lua可以在超出范围时重用函数引用吗?

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