luaiterable-unpackingargument-unpacking

How to "pack" a variable amount of outputs from a function in Lua?


I have a function in Lua that gives a variable number of outputs. How can I get all its outputs, regardless of how many outputs it has?

function my_function()
    -- whatever
end

outputs_list = my_function()

The above example doesn't work because outputs_list gets only the first output of the function, and all the others are discarded. I want outputs_list to contain all the outputs of the function so I can retrieve them later.

I think this is equivalent in python to doing *outputs_list = my_function()


Solution

  • In general, you can capture the values into a table

    local t = { foo() }
    

    but it may not be a sequence if the function returns nil values that create holes in the list.

    select may be used to choose where to begin capturing return values.

    -- capture the second return value and onwards
    local t = { select(2, foo()) }
    

    In Lua 5.2+, you also have access to table.pack(...), which

    Returns a new table with all arguments stored into keys 1, 2, etc. and with a field "n" with the total number of arguments. Note that the resulting table may not be a sequence, if some arguments are nil.

    The caveat about the resulting table not being a sequence means that looping over all the returned values may require a numeric for, instead of a generic one using ipairs.

    local function foo()
        return 'a', 'b', 'c', 'd', 'e'
    end
    
    local results = table.pack(foo())
    
    for i = 1, results.n do
        print(results[i])
    end
    
    a
    b
    c
    d
    e
    

    The opposite function is table.unpack.


    In Lua 5.1, you can polyfill table.pack as

    table.pack = function (...)
        local t = { ... }
        t.n = select('#', ...)
        return t
    end