Store multiple return values ββas named table keys
I have a Lua function that calculates some values ββand returns them. For example:
function calculateStats()
return { spin=1, zoom=2, rotate=3, dist=4 }
end
In one place where it is called, I need to store these values ββfor later comparison. Here I prefer them in a table, for naming purposes:
function foo:startup()
self.initialState = calculateStats()
end
However, there is another place where this function is called many times per second. To avoid unnecessary garbage collection, I would prefer not to allocate the table for the results, but instead store them as local variables. So now I want to switch to:
function calculateStats()
return 1, 2, 3, 4
end
function foo:onRenderFrame()
local spin, zoom, rotate, dist = calculateStats()
end
An unfortunate side effect of this is that I end up writing my startup function as:
function foo:startup()
local spin, zoom, rotate, dist = calculateStats()
self.initialState = {spin=spin,zoom=zoom,rotate=rotate,dist=dist}
end
Is there a better way to associate indexed return values ββwith names and store them in a table so that I don't repeat the same name three times in a row?
source to share
A simple pattern you can use is to simply pass the table in calculateStats
and then return it to the table, or just return it in unpacked form. For example:
function calculateStats(t)
if not t then return 1, 2, 3, 4 end
t.spin, t.zoom, t.rotate, t.dist = 1, 2, 3, 4
return t
end
This allows it to be kept foo:onRenderFrame
as is, but foo:startup
one small change is required:
function foo:startup()
self.initialState = calculateStats{}
end
source to share
You can use a third party macro package like LuaMacro or MetaLua to implement nice custom syntax, or use something like the following Lua code:
function varargsToTable( fields, ... )
local t = {}
for i = 1, select( '#', ... ) do
if fields[ i ] ~= nil then
t[ fields[ i ] ] = select( i, ... )
else
break -- no more known field names left, bail out
end
end
return t
end
-- maps position in return value list to field name:
statsNames = { "spin", "zoom", "rotate", "dist" }
function calculateStats()
return 1, 2, 3, 4
end
local statsTable = varargsToTable( statsNames, calculateStats() )
for k,v in pairs( statsTable ) do
print( k, v )
end
source to share
While these are still two assertions, this answers the need by removing all duplicate names without putting a conditional expression in an often called function:
function calculateStats()
return 1, 2, 3, 4
end
function foo:startup()
self.initialState = {}
self.initialState.spin, self.initialState.zoom,
self.initialState.rotate, self.initialState.dist = calculateStats()
end
function foo:onRenderFrame()
local spin, zoom, rotate, dist = calculateStats()
end
source to share