我知道我可以将功能引用存储在表中,并用参数拨打,例如第一个答案中的第一个答案
中描述的参数lua-执行存储在表中的函数
,但我需要为每个调用的表中存储参数。我该怎么做?
解释我想做什么。我想写一个转向行为课。如果您要计算转向力,则可以调用不同的功能(例如(目标(或追踪(目标((。
我希望能够"收集"所有函数调用并在末端执行它们(在表上循环并使用存储的参数执行每个函数(或取消所有内容。
可能吗?
另一个(可能更清洁的(替代方案:
function xxx(s1,s2,s3)
print(s1,s2,s3)
end
t = {}
t[#t+1] = { xxx, {'a','b','c'}}
t[#t+1] = { xxx, {'x','y','z'}}
for _,f in ipairs(t) do
f[1](table.unpack(f[2]))
end
如果已知可能的最大参数数,那么您可以在闭合时做一些简单的事情。
local function bind(f, p1, p2, p3, p4, p5)
return function()
return f(p1, p2, p3, p4, p5)
end
end
值类型将在绑定后不可变,并且所有参数将通过(甚至是nils(。
local hello = bind(print, 'hello', 123)
hello() --> hello 123 nil nil nil
当然,您也可以绑定到参考类型。
local coords = { x=0, y=0 }
local t1 = bind(function(t, n) t.x = t.x + n end, coords, 20)
local t2 = bind(function(t, n) t.y = t.y + n end, coords, 50)
t1(); print('transform1', coords.x, coords.y) --> 20 0
t2(); print('transform2', coords.x, coords.y) --> 20 50
t1(); print('transform1', coords.x, coords.y) --> 40 50
,您仍然可以将所有内容存储在桌子中。
local t = {
bind(function(a, b) return 'add', a + b end, 5, 5),
bind(function(a, b) return 'sub', a - b end, 5, 5),
bind(function(a, b) return 'mul', a * b end, 5, 5),
bind(function(a, b) return 'div', a // b end, 5, 5),
}
for _, f in ipairs(t) do
print(f())
end
--> add 10
--> sub 0
--> mul 25
--> div 1
如果要在表中存储一个函数和某些参数,然后用这些参数调用该函数,那么,您只需将参数与函数一起存储在表格中,然后将这些作为参数传递:
functions_with_parameters = {
{
f = function (a, b) return a + b end,
args = { 1, 2 }
},
{
f = function (a, b) return a - b end,
args = { 100, 90 }
}
}
for _, a in pairs(functions_with_parameters) do
print(a.f(a.args[1], a.args[2]))
end
// 3
// 10
这就是我要做的:
-- pack one func + args into a table
function record( f, ... )
return { func = f, n = select( '#', ... ), ... }
end
-- take a list/array/sequence of `record`ed functions & run them
function run( list )
for _, callinfo in ipairs( list ) do
callinfo.func( table.unpack( callinfo, 1, callinfo.n ) )
end
end
样本使用:
todo = { }
todo[#todo+1] = record( print, "foo", "blah", nil, 23 )
todo[#todo+1] = record( print, "baz" )
run( todo )
--> foo blah nil 23
--> baz
一些明显的变化包括在run
中执行pcall
(因此错误不会在中间中止它(,或添加一个额外的功能,该功能需要( list, f, ... )
并包含呼叫信息&将其附加到列表中。
如果您可以确定参数列表中间没有nil
,则可以简化为…
-- pack one func + args into a table
function record( f, ... )
return { func = f, ... }
end
-- take a list/array/sequence of `record`ed functions & run them
function run( list )
for _, callinfo in ipairs( list ) do
callinfo.func( table.unpack( callinfo ) )
end
end
…但是我强烈建议建议只有在完成代码的其余部分并且您知道(mease!(时才执行此操作,这很慢。。(如果有一个错误将意外nil
s引入参数列表中,则此版本将 alter参数列表 (通过删除元素(,而第一个将不变,无论是什么,是调试-Friendlier。(
如果您的空间确实很短,则可以通过不使用命名字段来节省一个值的空间
(附录:除LUA 5.2外,这似乎也比上面的其他两个变体要快一些 - 请参见下面的评论。(
-- (you can actually just do this inline)
function record( f, ... ) return { f, ... } end
-- take a list/array/sequence of `record`ed functions & run them
function run( list )
for _, callinfo in ipairs( list ) do
callinfo[1]( table.unpack( callinfo, 2 ) )
end
end
…但这取决于参数的数量,实际上可能浪费空间!(对于x86_64上的香草(puc-rio(lua,它将16个字节(1台电视(保存为0、1、3或7个参数,对2或6个参数无能为力,wastes 32字节为4、16 bytes for 4,和112个字节的8个参数(以及相同的两个模式不断增长/重复(。(