Question

For example, I have a table

table.insert( t, 1, function()
                        print ("rock");
                    end );

Is there any way to get function name from this table. I know that I can store name like a key, but what if I want to keep numeric index and also I want to know function name? Is there any way to do it? Thanks, on advance.

Was it helpful?

Solution

Say you have this code:

t = {}
x = 5
table.insert(t, 1, x)

t would then be {[1] = 5}. "5" is just a number - it has no name, and isn't associated with the variable "x"; it's a value.
In Lua, functions are treated exactly the same way, as values:

t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)

The value of x is not associated with x in any way, shape, or form. If you want to manually name a function, you can do it by wrapping the function in a table, for example:

t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
    name = "MyFunctionName",
    func = x
})

That is how you would do it!

...unless..

..you break the rules!
When Lua was developed, the developers realised that the anonymous nature of functions would make productive error messages difficult to produce, if not impossible.
The best thing you'd see would be:

stdin: some error!
  stdin: in function 'unknown'
  stdin: in function 'unknown'

So, they made it so that when Lua code was parsed, it would record some debug information, to make life easier. To access this information from Lua itself, the debug library is provided.
Be very careful with functions in this library.

You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.

To achieve your desired effect, you must use the debug.getinfo function; an example:

x = function()
    print("test!")
    print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"

Unfortunately, the form of debug.getinfo that operates directly on a function doesn't fill the name argument (debug.getinfo(x, "n").name == nil) and the version above requires you to run the function.
It seems hopeless!

...unless..

..you really break the rules.
The debug.sethook function allows you to interrupt running Lua code at certain events, and even change things while it's all happening. This, combined with coroutines, allows you to do some interestingly hacky stuff.
Here is an implementation of debug.getfuncname:

function debug.getfuncname(f)
    --[[If name found, returns
            name source line
        If name not found, returns
            nil  source line
        If error, returns
            nil  nil    error
    ]]
    if type(f) == "function" then
        local info = debug.getinfo(f, "S")
        if not info or not info.what then
            return nil, nil, "Invalid function"
        elseif info.what == "C" then
            -- cannot be called on C functions, as they would execute!
            return nil, nil, "C function"
        end
        --[[Deep magic, look away!]]
        local co = coroutine.create(f)
        local name, source, linedefined
        debug.sethook(co, function(event, line)
            local info = debug.getinfo(2, "Sn")
            name = info.namewhat ~= "" and info.name or nil
            source, linedefined = info.short_src, info.linedefined
            coroutine.yield() -- prevent function from executing code
        end, "c")
        coroutine.resume(co)
        return name, source, linedefined
    end
    return nil, nil, "Not a function"
end

Example usage:

function test()
    print("If this prints, stuff went really wrong!")
end

print("Name = ", debug.getfuncname(test))

This function isn't very reliable - it works sometimes, and doesn't others. The debug library is very touchy, so it's to be expected.

Note that you should never use this for actual release code! Only for debugging!
The most extreme case that is still acceptable is logging errors on piece of released software, to help the developer fix issues. No vital code should depend on functions from the debug library.

Good luck!

OTHER TIPS

The function hasn't got any name. If you want you can assign it to a named variable:

theFunction = t[1]
-- Call it:
theFunction()

If what you want is storing a named function to the table, define it beforehand and use its name to store it:

theFunction = function()
                  print ("rock");
              end

table.insert(t, 1, theFunction)

If this is not what you meant, give more details; for example how you would like to access the function. You're question is a bit misty.

The thing is table.insert considers the table as a sequence, only with numeric keys.

If you want to be able to call the function as t.fun() you'll have to use the table as an associative array and hence use a string as key. (BTW any type except nil or NaN are allowed as key)

t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.

You might also notice that functions are passed by reference. So all functions are actually anonymous, and are just stored as a value to a certain key or variable.

You can store the names in a separate table.

functions = {}
functionNames = {}

function addFunction(f, name)
  table.insert(functions, f)
  functionNames[name] = f
end

To get the function, you can use the index. Once you have the function, you can get its name from function_names:

f = functions[3]
name = functionNames[f]

Good luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top