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?

+3


source to share


4 answers


If you are using Lua 5.2 try this:



local function calculateStats()
  return 1, 2, 3, 4
end

function foo:startup()
   local _ENV=self.initialState
   spin, zoom, rotate, dist = calculateStats()
end

function foo:onRenderFrame()
   local spin, zoom, rotate, dist = calculateStats()
end

      

+1


source


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

      

+3


source


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

      

+1


source


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

      

+1


source







All Articles