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.
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())