lualua-5.4

How to store a table method in a different table?


I would like to store methods that are associated with a table, so that I can randomly select one of the function using math.random. Storing functions in a table and calling those functions is straight forward, as shown below:

function funcA()
    print("A")
end

functionTable = {funcA}
functionTable[1]()

However, I cannot store a function from a table (a method?) in a new table. The following code will return in an Error (Lua 5.4): function arguments expected near '}'

local functionStore = {}

function functionStore:funcA()
    print("A")
end

functionStore:funcA()
functionTable = {functionsStore:funcA}
functionTable[1]()

I think the colon (:) means that I'm already calling the function?, and then the error would make sense, but I would like to store the function in the table.

What Am I doing wrong here?


Solution

  • The problem is that the colon is a special syntactic sugar for function calls to pass the variable / expression preceding it as first argument to the function; it can not be used as an expression. You can however write yourself a function that "curries" the self argument, creating a closure:

    local function curry_self(self, methodname)
        return function(...) return self[methodname](self, ...) end
    end
    

    then you can use this as follows:

    functionStore:funcA()
    functionTable = {curry_self(functionsStore, "funcA")}
    functionTable[1]()
    

    Alternatively, you may pass self as you invoke the function:

    functionStore:funcA()
    functionTable = {functionStore.funcA}
    functionTable[1](functionStore) -- pass functionStore as `self`
    

    In your case, you don't need the colon at all though - you don't even use self in your function! Thus, you may use:

    local functionStore = {}
    
    function functionStore.funcA()
        print("A")
    end
    
    functionStore.funcA()
    functionTable = {functionsStore.funcA}
    functionTable[1]()
    

    you can put functions in a table without using the colon, using just the dot to assign them to table fields.