Callback argument handling

setArgs and getArgs - by Mikk -

setArgs and getArgs are used to remember and retreive arguments for callback functions in a reasonably memory-efficient way. Note however that if your callback argument list typically is longer than 2 arguments, it is both more CPU and memory efficient to simply use an integer-indexed subtable and table.unpack.

setArgs(myTable, "name", list,of,arguments,...)

list,of,arguments,extra,arguments,... = getArgs(myTable, "name"[, extra, arguments, ...])

Arguments

 * (myTable, "name", list,of,arguments,...)


 * myTable : Table - where to store the arguments
 * "name" : String - prefix to give the arguments, if you are storing arguments for multiple callbacks, otherwise ""
 * ... : List of arguments to be stored

Returns

 * nothing

Arguments

 * (myTable, "name"[, ...])


 * myTable : Table - where to retreive the arguments from
 * "name" : String - prefix used in setArgs
 * ... : (optional) - extra arguments to use after the stored ones

Returns

 * All arguments stored by setArgs, optionally followed by the extra arguments supplied to getArgs

Example 1
Just demonstrating how setArgs and getArgs actually work

function out(...) for i=1,select("#", ...) do    print(i.."="..tostring(select(i,...))) end end tbl = {} setArgs(tbl, "myArgList", "a", nil, "3") out( getArgs(tbl, "myArgList", "extra", nil, "cheese") )

Result
1=a 2=nil 3=3 4=extra 5=nil 6=cheese

Example 2
Demonstrating how callbacks could be implemented in a "library" / addon that wants to be able to accept callback registrations from other sources

"Library"
local mytable = {} local function myUpdateHandler(this, delay) if mytable.callback then mytable.callback( getArgs(mytable, "arg", delay) ) end end function RegisterOnUpdateCallback(func, ...) mytable.callback = func setArgs(mytable, "arg", ...) end

(There obviously needs to be a frame created that calls myUpdateHandler via OnUpdate also, but that's out of scope for the example)

"User"
function MyMod:OnUpdate(delay) print("OnUpdate fired after " delay " seconds"); end function MyMod:Initialize SetOnUpdateCallback(MyMod.OnUpdate, self) end

Code
local getArgs do  local numargs local function _get(t, str, i, ...) if i&lt;=numargs then return t[format("%s%d", str, i)], _get(t, str, i+1, ...) end return ... end function getArgs(t, str, ...) numargs = t[str.."#" or 0] return _get(t,str,1, ...) end end local function setArgs(t, str, ...) local n = select("#", ...) for i=1,n do    t[format("%s%d",str,i)]=select(i,...) end for i=n+1, (t[str.."#"] or 0) do  	t[format("%s%d",str,i)]=nil end t[str.."#"] = n end