英文:
Capturing rest of returned values from function into list
问题
Here's the translated code portion:
给定简单的函数:
function pullEvent()
return "eventName", "eventArg1", "eventArg2", "eventArg3", "eventArg4"
end
其中返回值的数量取决于第一个返回值,如何将第一个返回值捕获到一个变量中,将其余所有值捕获到列表中?
我可以想象如下方式:
local eventName, { eventArgs } = pullEvent()
但这是无效的语法。
我现在的做法是:
local event = { pullEvent() }
local eventName, eventArgs = event[1], { table.unpack(event, 2) }
这个方法可行,但我想问一下,是否有更简洁的方法。最好不要创建 event
变量。
英文:
Given simple function:
function pullEvent()
return "eventName", "eventArg1", "eventArg2", "eventArg3", "eventArg4"
end
where number of returned values depends on first returned value, how can I capture first returned value into one variable and all remaining into list?
I can imagine something like:
local eventName, { eventArgs } = pullEvent()
but that is invalid syntax.
Way I'm doing it now is:
local event = { pullEvent() }
local eventName, eventArgs = event[1], { table.unpack(event, 2) }
which works, but I'd like to ask, if there is shorter way of doing it. Preferably without creating event
variable.
答案1
得分: 6
通常,您需要使用函数和/或 select
来处理可变参数。在您的情况下:
local function nameAndArgs(head, ...)
return head, {...}
end
然后您可以这样使用:
-- eventArgs 将是一个表
local eventName, eventArgs = nameAndArgs(pullEvent())
这个简单的解决方案假设事件参数永远不会是 nil
,否则您可能会得到一个带有尾随 nil
的表;可变参数 1, nil, 2, nil
将变成表 {[1] = 1, [3] = 2}
- 在更新的 Lua 版本中,您可以使用 table.pack
来让 Lua 存储可变参数的计数(select("#", ...)
)在表的 n
字段中,允许精确地将其恢复为可变参数,使用 table.unpack(t, 1, t.n)
。
然而,您很可能不想打包表。您只想要基于事件名的“开关”,将参数分配给变量。这可能看起来如下:
local function handleEvent(eventName, ...)
if eventName == "foo" then
local bar = ...
-- 做一些事情
elseif eventName == "bar" then
local foobar, quux = ...
-- 做一些事情
else
error"未知事件"
end
end
handleEvent(pullEvent())
或者,更优雅地(可能更高效,如果您有许多处理程序,因为它利用 O(1) 的哈希表查找而不是平均 O(n) 比较),使用“函数分派表”模式:
local eventHandlers = {
foo = function(bar)
-- 做一些事情
end,
bar = function(foobar, quux)
-- 做一些事情
end,
}
local function handleEvent(eventName, ...)
return assert(eventHandlers[eventName], "未知事件")(...)
end
handleEvent(pullEvent())
英文:
Generally, you need to use functions and/or select
to deal with varargs. In your case:
local function nameAndArgs(head, ...)
return head, {...}
end
which you can then use as
-- eventArgs will be a table
local eventName, eventArgs = nameAndArgs(pullEvent())
this simple solution assumes that the event args are never nil
, otherwise you potentially get a table with holes where trailing nil
s are stripped; the vararg 1, nil, 2, nil
would become the table {[1] = 1, [3] = 2}
- in newer Lua versions you could use table.pack
to have Lua store the count of the vararg (select("#", ...)
) in the n
field of the table, allowing exactly restoring it to a vararg using table.unpack(t, 1, t.n)
.
However, you most likely don't want to pack tables. All you want is a "switch" based on the event name which assigns the arguments to variables. This might look as follows:
local function handleEvent(eventName, ...)
if eventName == "foo" then
local bar = ...
-- do something
elseif eventName == "bar" then
local foobar, quux = ...
-- do something
else
error"unknown event"
end
end
handleEvent(pullEvent())
or, more elegantly (and potentially more efficiently if you have many handlers, since it leverages an O(1) hash table lookup rather than doing O(n) comparisons on average), using the "dispatch table of functions" pattern:
local eventHandlers = {
foo = function(bar)
-- do something
end,
bar = function(foobar, quux)
-- do something
end,
}
local function handleEvent(eventName, ...)
return assert(eventHandlers[eventName], "unknown event")(...)
end
handleEvent(pullEvent())
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论