Reputation: 2018
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.
Upvotes: 1
Views: 1803
Reputation: 5149
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!
Upvotes: 6
Reputation: 52621
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!
Upvotes: 0
Reputation: 9549
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.
Upvotes: 0
Reputation: 4137
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.
Upvotes: 1