将函数返回的其余值捕获到列表中。

huangapple go评论61阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年6月27日 21:22:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定