Lua multiple assignment with tables
BLUF
There's no straight forward or elegant way to do this. You'll have to do it manually like this
local r = { f() } --> store all returned values in r
local bar = { }
local c = string.byte 'a' --> start with 'a'
for _, v in ipairs(r) do
local t = string.char(c)
bar[t] = v --> assign each value to respective letter
c = c + 1
end
If you'd had a, b, c = foo()
you'd get all the three values assigned to the three variables. However, you've
bar = { a, b, c = foo() }
This table constructor expression will get interpreted as the keys a
, b
, c
getting inserted into the table, with only the last key having an associated value (aside: keys with no associated value are taken as nil
; hence a
and b
never get inserted). Since there's only one variable to take the values returned by foo
, except the first everything else it returns are discarded.
Alternatively bar = { foo() }
will assign all values returned by foo
as array values of bar
. However, the key to access these would [1]
, [2]
, etc. and not 'a'
, 'b'
, etc.
Read below to know when the returned values get discarded and when they don't.
TL;DR All returned values are retained only when the function call is the last/only expression in a list of expressions; elsewhere all except the first are discarded.
Function call as a statement
In Lua, when we return multiple results from a function, all of them get discarded if the function call is a statement by itself.
foo()
will discard all three return values.
Function call in an expression
If it's used in an expression, only the first will be retained and everything else will be discarded.
x = foo() - 1
print(x) -- prints 0; the values 2, 3 are discarded
Function call in an expression list
The entire list of values returned is retained only when the call appears as the last/only item in a list of expressions. Such list of expressions occur at four places in Lua:
Multiple assignment
E.g.
local a, b, c, d = 0, f()
. Hereb
,c
,d
get the values1
,2
,3
respectively.Table constructor
E.g.
local t = { 0, f() }
. All values returned byf
are put intot
following the first0
.Function call arguments
E.g.
g(a, f())
.g
would receive 4, not 2, arguments.a
and the three values fromf
.return
statementE.g.
return 'a', f()
. Additional to the string'a'
, all values returned byf
will be received at the calling end.
In all these situations, had f
appeared not as the last expression in the list or wasn't the only expression, then all values it returned except the first would've been discarded.
Multiple assignment statement
In the multiple assignment statement, when the number of values assigned is lesser than number of variables, the extra variables be assigned to nil
. When it's the other way around i.e if the number of variables are lesser, the extra values are discarded.
a, b, c = 1, 2 -- a = 1, b = 2, c = nil
a, b, c = 1, 2, 3, 4 -- 4 gets discarded
bar = {}
bar.a, bar.b, bar.c = foo()