Question

Using Lua, I'm trying to dynamically call a function with parameters. I want to send a string to be parsed in a way that:

  • 1st argument is a class instance "Handle"
  • 2nd is the function to be called
  • All that is left are arguments

"modules" is a a table like { string=<instance of a class> }
split() is a simple parser that returns a table with indexed strings.

function Dynamic(msg)
    local args = split(msg, " ")
    module = args[1]
    table.remove(args, 1)
    if module then
        module = modules[module]
        command = args[1]
        table.remove(args, 1)
        if command then
            if not args then
                module[command]()
            else
                module[command](unpack(args))  -- Reference 1
            end
        else
            -- Function doesnt exist
        end
    else
        -- Module doesnt exist
    end
end

When I try this with "ignore remove bob", by "Reference 1", it tries to call "remove" on the instance associated with "ignore" in modules, and gives the argument "bob", contained in a table (with a single value).

However, on the other side of the call, the remove function does not receive the argument. I even tried to replace the "Reference 1" line with

module[command]("bob")

but I get the same result.

Here is the other function, which does not receive the argument "bob" :

function TIF_Ignore:remove(name)
    print(name)  -- Reference 2
    TIF_Ignore:rawremove(name)
    TIF_Ignore:rawremovetmp(name)
    print(title.. name.. " is not being ignored.")
end

I added "Reference 2" in my code when I was trying to figure out what was wrong. When I do "ignore remove bob", or when I replace the "unpack(args)" with "bob" on "Reference 1", the variable "name" in "remove" is still nil.

Was it helpful?

Solution

The declaration function TIF_Ignore:remove(name) is equivalent to function TIF_Ignore.remove(self, name). Note the use of colon in the first case, it adds extra hidden parameter to emulate OOP and classes. The way you call the function, you pass "bob" as the self parameter instead of name.

To fix this you can make remove "static function" like this: function TIF_Ignore.remove(name). However, you'll also have to change rawremove and rawremovetmp in a similar fashion, both declaration and calling site. The other (easier) option is not to remove module from the args table, it should be the first parameter passed.

OTHER TIPS

If you want to call a function defined with the colon : syntax, you have to pass it an additional argument, namely the table it is expecting. Because the particular example you give does not use self, you could switch to the dot . syntax, but in case you need the full generality, look to the code below:

function Dynamic(msg)
    local args   = split(msg, " ")
    local module = table.remove(args, 1)
    if module and modules[module] then
        module = modules[module]
        local command = table.remove(args, 1)
        if command then
            local command = module[command]
            command(module, unpack(args))
        else
            -- Function doesnt exist
        end
    else
        -- Module doesnt exist
    end
end

I have also fixed a number of minor problems:

  • Variables should be local.
  • args is always non-nil.
  • Lookup modules[module] might fail.
  • table.remove returns the element removed, and it's OK to call it on an empty table.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top