我遇到了一个古老的unpack bug,在Lua中我有一个可以包含nil值的数组,我想用nil值解压缩该数组。这似乎是不可能的。这种逻辑的替代方法是什么?
这是我尝试运行的代码
function InputSystem:poll(name, ...)
local system = self:findComponent(name)
local values, arr = {...}, {}
for i, v in pairs(values) do
arr[#arr+1] = system[v]
end
--If the first guy is null this does not work!! WHY
return unpack(arr, 1, table.maxn(values))
end
我的想法是我动态轮询输入系统,以便只返回想要的值:
local dragged,clicked,scrolled = self.SystemManager:findSystem('Input'):poll('Mouse', 'Dragged', 'Clicked', 'Scrolled')
有什么想法吗?谢谢
编辑:
我似乎不太了解Lua。我想返回与...传递的变量数量相同的变量,但是在循环中,如果找不到该属性,我以为会将其设置为nil,但这似乎是错误的。
function InputSystem:poll(name, ...)
local system = self:findComponent(name)
local values, arr = {...}, {}
for i, v in pairs(values) do
arr[#arr+1] = system[v] --If not found set nil
end
--I want this to return the length of ... in variables
--Example I pass 'Dragged', 'Clicked' I would want it to return nil {x:1,y:1}
return unpack(arr, 1, table.maxn(values))
end
显然我是Lua大师...
答案 0 :(得分:3)
您应使用data1
和GPU1
来保存table.pack
。如果您使用Lua 5.2或更高版本,则可以删除兼容性代码段。
table.unpack
nil
答案 1 :(得分:1)
for i, v in pairs(values) do
arr[#arr+1] = system[v] -- This doesn't work!
end
实施中的问题是,您希望将nil追加到数组中以增加其长度,但事实并非如此:
local arr = {1, 2, 3}
print(#arr) --> 3
arr[#arr+1]=nil
print(#arr) --> 3
本质上,您想要的是一个map
函数,该函数接受一个元素列表,对每个元素应用一个函数fn
并返回结果列表。
通常,可以很容易地将其实现为tail-recursive函数,如下所示:
local function map(fn, elem, ...)
if elem then return fn(elem), map(fn, ...)
end
这对于nil
参数并不能很好地解决,因为当剩下的参数尚待处理时,它们会使条件变为假,但是我们可以使用select
对其进行修改,以避免这种情况:< / p>
local function map(fn, elem, ...)
if select('#', ...)>0 then return fn(elem), map(fn, ...)
else return fn(elem) end
end
-- This implementation still gets TCOd :)
然后您可以像这样使用它:
map(string.upper, 'hello', 'world') --> 'HELLO', 'WORLD'
您想将...
中的每个值映射到表中的相应值,但是由于map
将函数作为其第一个值,因此我们可以将其包装在函数中。而且由于在编写代码时我们不知道该表,因此我们必须在运行时生成函数:
local function index(table)
return function(idx)
return table[idx]
end
end
现在我们可以这样做:
map(index{'hello', 'world'}, 1, 2) --> 'hello', 'world'
-- index{'hello', 'world'} returns a function that indexes the given table
-- with its first argument and returns the value
然后,您可以像这样编写InputSystem
函数:
function InputSystem:poll(name, ...)
return map(index(self:findComponent(name)), ...)
end
很明显,在这种情况下,我们不需要该通用映射函数,因为我们总是在索引一个表。我们可以重写map来使用像这样的表:
local function map(tab, elem, ...)
if select('#', ...)>0 then return tab[elem], map(tab, ...)
else return tab[elem] end
end
,主要功能将变为:
function InputSystem:poll(name, ...)
return map(self:findComponent(name), ...)
end
我注意到的另一件事:
for i, v in pairs(values) do
arr[#arr+1] = system[v] --If not found set nil
end
pairs
会无序迭代,因此您的行for i, v in pairs(values) do
可能会完全重新排列值。自从您进一步写local dragged,clicked,scrolled = self.SystemManager:findSystem...
后,我相信您希望返回值保持顺序。