Lua的:与无解压?另类?

问题描述 投票:0回答:2

我碰到多岁的老unpack bug,在那里我有在Lua的数组可以包含零值,我想解开与零值的数组;这似乎是不可能的。什么是替代这个逻辑?

这里是我试图运行代码

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。我是想返回的变量相同数量的...传入,但在循环,如果未找到属性,我认为这将其设置为无,但这似乎是错误的。

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主...

lua love2d
2个回答
0
投票
for i, v in pairs(values) do
  arr[#arr+1] = system[v] -- This doesn't work!
end

您的实现的问题是,你希望追加零到一个数组来增加它的长度,它不会:

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避免这种修改:

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

很显然,我们并不需要在这种情况下一般的地图功能,因为我们一直在索引的表。我们可以重写地图使用一个表是这样的:

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...我相信你所期望的回报值保持秩序。


3
投票

您应该使用table.packtable.unpack保持nils。如果您使用的Lua 5.2或以上,您可以删除兼容性片段。

-- Backwards compatibility
table.pack = table.pack or function(...) return { n = select("#", ...), ... } end
table.unpack = table.unpack or unpack

function test(...)
    local values = table.pack(...)
    local arr = {}
    for i, v in pairs(values) do
        -- iterates only the non-nil fields of "values"
        arr[i] = 10*v
    end
    return table.unpack(arr, 1, values.n)
end

print(test(nil, 1, nil, 2, nil, nil, 3))
$ lua5.3 test.lua
nil 10  nil 20  nil nil 30
$ lua5.2 test.lua
nil 10  nil 20  nil nil 30
$ lua5.1 test.lua
nil 10  nil 20  nil nil 30
$ luajit test.lua
nil 10  nil 20  nil nil 30
© www.soinside.com 2019 - 2024. All rights reserved.