Lua - Repeat until recurent table to except 'attempt to index a nil value' - lua

Ok so i will show an exemple
I want do this :
local x = {}
repeat
-- wait function
until x.lel.ciao
But i've this error :
input:3: attempt to index a nil value (field 'lel')
So i can just do this :
local x = {}
repeat
-- wait function
until x.lel and x.lel.ciao
but if i've a long path how can i do ?
like :
x.lel.ciao.value1.title1.text1
i dont want do :
local x = {}
repeat
-- wait function
until x.lel and x.lel.ciao and x.lel.ciao.value1 and x.lel.ciao.value1.title1 and x.lel.ciao.value1.title1.text1
Someone have an idea ? like a function safepath(x.lel.ciao.value1.title1.text1)

Just like Egor's comment (thanks Egor), debug.setmetatable allows you to set a metatable for object type (not object instance).
This comes with an issue,
All the objects of that type will also inherit the mtatable.
This means, you will experience issues that will make your code harder to debug, as it is definitely important to get this kind of feedback from nil values.
Take in example the following code:
debug.setmetatable(nil, { __index = {} })
repeat
. . . -- Your code goes here
until x.lel.ciao.value1.title1.text1
function getFrom(data, value)
return date[value]
end
. . . -- More code
From this simple scope perspective, you might quickly see the issue, but imagine this code being buried by thousands of lines and functions.
You will eventually run into insanity as it only returns nil, which shouldn't happen at all because, well, you are sure your data variable has such value, right?
In order to avoid such thing from happening, you should safely do it like this:
debug.setmetatable(nil, { __index = {} })
repeat
. . . -- Your code goes here
until x.lel.ciao.value1.title1.text1
debug.setmetatable(nil, nil)
According to the Lua reference, setting a metatable to nil will remove the metatable, this way you will only temporally ignore feedback from nil while running inside the repeat loop.

Related

Lua is it possible to "halt" any code execution from within a table?

Something that intrigues me about Lua is the fact that you can run any function from within a table, regardless of whether it returns anything or not, an example of what I am talking about is:
local my_table = {
print("output from a table!");
warn("more output from a table!");
};
The funny thing is that as soon as this table is created both functions inside of it are ran, and both my_table[1] and [2] are equal to nil (because print and warn do not return a value). However is there any way to per-say "halt" both functions from executing whenever the table is created, and possibly even "start" running them later, if a certain condition is met or not?
I would appreciate any help; Thanks
You're not storing functions in a table that way, you're storing results of calls.
If you need functions, create anonymous functions explicitly.
local mytable = {
function() print("output from a table!") end,
function() warn("more output from a table!") end
}
If you don't like this way, there's another. Capture function and arguments in a lexical closure, and apply stored arguments when that closure will be called.
local function delay(func, ...)
local args = {...}
return function()
func(table.unpack(args))
end
end
local mytable = {
delay(print, "output from a table!"),
delay(warn, "more output from a table!")
}
mytable[1]()
mytable[2]()

attempt to call a nil value

for i = 1, groupA:getNumChildren() do
local sprite = groupA:getChildAt(i)
if cute.anim[1]:collidesWith(sprite) then
youLoose()
end
end
local function youLoose()
local font3 = TTFont.new("billo.ttf", 20, " 1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,?")
local text7 = TextField.new(font2, "gameover")
text7:setPosition(200, 100)
stage:addChild(text7)
GameLost = Bitmap.new(Texture.new("gameover.jpg"))
Background : removeFromParent()
groupA : removeFromParent()
stage: addChild(GameLost)
alert()
end
It gives an error that says 'attempt to call global youLoose (a nil value), where am I doing it wrong?
Note that collideswith is not the same as collidesWith; if that error you posted is correct, then you posted code that is different from what you are using. It could be that the method really is called collidesWith (it appears to be if it is the one from sprite1), but you used collideswith. Alternatively, if the code posted is what you used, then the error is likely attempt to call collideswith(a nil value), so cute.anim[1] is not a sprite1 object, but it is not nil either otherwise the error would be different.
Once you have fixed this, you'll notice that youLoose is defined after that for loop, when you call youLoose() it is not yet defined. You're going to have to move the local function youLoose() function to before the loop. Because the loop is not itself in a function, but is at module level, it gets executed before any following code, so any functions (local or global) that are used in the loop must be defined before the loop.
Note that "loose" does not mean the same as "lose". Check Grammar-monster to see difference. Probably everywhere you have the word "loose" you should change to "lose".

Get name of argument of function in lua

When call a lua function like
PrintMe(MyVariableName)
I would like to be able to actually print "MyVariableName" and not it's value(well, for demo purposes).
Obviously I could just pass the string but that requires extra quotes and I also would like to print it's value.
e.g.,
MyVariable = 4
PrintVariable(MyVariable)
Would print "MyVariable is 4" or whatever
I do not want to have to duplicate the name and variable like
PrintVariable(MyVariable, "MyVariable")
as this is unnecessary duplication.
Can lua handle it?
What I'm doing now is passing the variable name in quotes and using loadstring to get the value but I would like to just pass the variable directly without the extra unnecessary quotes(which I thought debug.getlocal did but it ends up returning the value instead of the name).
Here is mock example
function printme1(var, val)
print(var.." = "..val)
end
function printme2(v)
local r
loadstring("r = "..v)() -- equivalent to r = a but must be used since v is a string representing a and not the object a
print(v.." = "..tostring(r))
end
function printme3(v)
-- unknown
end
a = 3
printme1("a", a)
printme2("a")
printme3(a)
In this case all 3 should print the same thing. printme3 obviously is the most convenient.
You can't say PrintVariable(MyVariable), because Lua gives you no way of determining which variable (if any; a constant could have been used) was used to pass an argument to your function. However, you can say PrintVariable('MyVariable') then used the debug API to look for a local variable in the caller's scope which has that name:
function PrintVariable(name)
-- default to showing the global with that name, if any
local value = _G[name]
-- see if we can find a local in the caller's scope with that name
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break -- no more locals to check
elseif localname == name then
value = localvalue
end
end
if value then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("No variable named '%s' found.", name))
end
end
Now you can say:
PrintVariable('MyVariable')
While in this case will print "MyVariable = 4".
Not, if you really want to do this without the quotes, you could check the caller's locals for variables that have a supplied value, but that's occasionally going to give you the wrong variable name if there is more than one variable in the caller's scope with a given value. With that said, here's how you'd do that:
function PrintVariable(value)
local name
-- see if we can find a local in the caller's scope with the given value
for i=1,math.huge do
local localname, localvalue = debug.getlocal(2,i,1)
if not localname then
break
elseif localvalue == value then
name = localname
end
end
-- if we couldn't find a local, check globals
if not name then
for globalname, globalvalue in pairs(_G) do
if globalvalue == value then
name = globalname
end
end
end
if name then
print(string.format("%s = %s", name, tostring(value)))
else
print(string.format("No variable found for the value '%s'.", tostring(value)))
end
end
Now you can say PrintVariable(MyVariable), but if there happened to be another variable in the caller's scope with the value 4, and it occurred before MyVariable, it's that variable name that will be printed.
you can do stuff like this with the debug library... something like this does what you seem to be looking for:
function a_func(arg1, asdf)
-- if this function doesn't use an argument... it shows up as (*temporary) in
-- calls to debug.getlocal() because they aren't used...
if arg1 == "10" then end
if asdf == 99 then end
-- does stuff with arg1 and asdf?
end
-- just a function to dump variables in a user-readable format
function myUnpack(tbl)
if type(tbl) ~= "table" then
return ""
end
local ret = ""
for k,v in pairs(tbl) do
if tostring(v) ~= "" then
ret = ret.. tostring(k).. "=".. tostring(v).. ", "
end
end
return string.gsub(ret, ", $", "")
end
function hook()
-- passing 2 to to debug.getinfo means 'give me info on the function that spawned
-- this call to this function'. level 1 is the C function that called the hook.
local info = debug.getinfo(2)
if info ~= nil and info.what == "Lua" then
local i, variables = 1, {""}
-- now run through all the local variables at this level of the lua stack
while true do
local name, value = debug.getlocal(2, i)
if name == nil then
break
end
-- this just skips unused variables
if name ~= "(*temporary)" then
variables[tostring(name)] = value
end
i = i + 1
end
-- this is what dumps info about a function thats been called
print((info.name or "unknown").. "(".. myUnpack(variables).. ")")
end
end
-- tell the debug library to call lua function 'hook 'every time a function call
-- is made...
debug.sethook(hook, "c")
-- call a function to try it out...
a_func("some string", 2012)
this results in the output:
a_func(asdf=2012, arg1=some string)
you can do fancier stuff to pretty this up, but this basically covers how to do what you're asking.
I have bad news, my friend. You can access function parameter names as they appear at the top of the function, but the data to access exactly what they were named in the calling function does not exist. See the following:
function PrintVariable(VariableToPrint)
--we can use debug.getinfo() to determine the name 'VariableToPrint'
--we cannot determine the name 'MyVariable' without some really convoluted stuff (see comment by VBRonPaulFan on his own answer)
print(VariableToPrint);
end
MyVariable = 4
PrintVariable(MyVariable)
To illustrate this, imagine if we had done:
x = 4
MyVariable = x
MyOtherVariable = x
x = nil
PrintVariable(MyVariable)
Now if you were Lua, what name would you attach in the metadata to the variable that ends up getting passed to the function? Yes, you could walk up the stack with debug.getint() looking for the variable that was passed in, but you may find several references.
Also consider:
PrintVariable("StringLiteral")
What would you call that variable? It has a value but no name.
You could just use this form:
local parms = { "MyVariable" }
local function PrintVariable(vars)
print(parms[1]..": "..vars[1])
end
local MyVariable = "bar"
PrintVariable{MyVariable}
Which gives:
MyVariable: bar
It isn't generic, but it is simple. You avoid the debug library and loadstring by doing it this way. If your editor is any good, you could write a macro to do it.
Another possible solution is add this facility your self.
The Lua C API and source is pretty simple and extendable.
I/we don't know the context of your project/work but if you ARE making/embedding your own Lua build you could extend the debug library with something to do this.
Lua passes it's values by reference, but unknown offhand if these contain a string name in them and if so if easily accessible.
In your example the value declaration is the same as:
_G["MyVariable"] = 4
Since it's global. If it were declared local then like others stated here you can enumerate those via debug.getlocal(). But again in the C context of the actual reference context it might not matter.
Implement a debug.getargumentinfo(...) that extends the argument table with name key, value pairs.
This is quite an old topic and I apologize for bringing it back to life.
In my experience with lua, the closest I know to what the OP asked for is something like this:
PrintVariable = {}
setmetatable(PrintVariable, {__index = function (self, k, v) return string.format('%s = %s', k, _G[k]) end})
VAR = 0
VAR2 = "Hello World"
print(PrintVariable.VAR, PrintVariable.VAR2)
-- Result: VAR = 0 VAR2 = Hello World
I do not give more explanation, because the code is quite readable, however:
What happens here is simple, you only set a metatable to the PrintVariable variable and add the __index metamethod that is called when the table is forced to search for a value in its index, thanks to this functionality you can achieve what you see in the example.
Reference: https://www.lua.org/manual/5.1/manual.html
I hope that future and new visitors will find this helpful.

How to set name for function which is in the table

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.
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!
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!

Metamethod lookup through __index?

I've implemented my own class system and I'm having trouble with __tostring; I suspect a similar issue can happen with other metamethods, but I haven't tried.
(Brief detour: each class has a __classDict attribute, holding all methods. It is used as the class instances' __index. At the same time, the __classDict's __index is the superclass' __classDict, so methods in superclasses are authomatically looked up.)
I wanted to have a "default tostring" behavior in all instances. But it didn't work: the "tostring" behavior doesn't "propagate" through subclasses correctly.
I've done this test exemplifying my issue:
mt1 = {__tostring=function(x) return x.name or "no name" end }
mt2 = {}
setmetatable(mt2, {__index=mt1})
x = {name='x'}
y = {name='y'}
setmetatable(x, mt1)
setmetatable(y, mt2)
print(x) -- prints "x"
print(mt2.__tostring(y)) -- prints "y"
print(y) -- prints "table: 0x9e84c18" !!
I'd rather have that last line print "y".
Lua's "to_String" behaviour must be using the equivalent of
rawget(instance.class.__classDict, '__tostring')
instead of doing the equivalent of
instance.class.__classDict.__tostring
I suspect the same happens with all metamethods; rawget-equivalent operations are used.
I guess one thing I could do is copying all the metamethods when I do my subclassing (the equivalent on the above example would be doing mt2.__tostring = mt1.__tostring) but that is kind of inelegant.
Has anyone fought with this kind of issue? What where your solutions?
I suspect the same happens with all metamethods; rawget-equivalent operations are used.
That is correct.
from the lua manual:
... should be read as rawget(getmetatable(obj) or {}, event). That is, the access to a metamethod does not invoke other metamethods, and the access to objects with no metatables does not fail (it simply results in nil).
Generally each class has its own metatable, and you copy all references to functions into it.
That is, do mt2.__tostring = mt1.__tosting
Thanks to daurnimator's comments, I think I found a way to make metamethods "follow" __index as I want them to. It's condensed on this function:
local metamethods = {
'__add', '__sub', '__mul', '__div', '__mod', '__pow', '__unm', '__concat',
'__len', '__eq', '__lt', '__le', '__call', '__gc', '__tostring', '__newindex'
}
function setindirectmetatable(t, mt)
for _,m in ipairs(metamethods) do
rawset(mt, m, rawget(mt,m) or function(...)
local supermt = getmetatable(mt) or {}
local index = supermt.__index
if(type(index)=='function') then return index(t,m)(...) end
if(type(index)=='table') then return index[m](...) end
return nil
end)
end
return setmetatable(t, mt)
end
I hope it is straightforward enough. When a new metatable is set, it initializes it with all metamethods (without replacing existing ones). These metamethods are prepared to "pass on" requests to "parent metatables".
This is the simplest solution I could find. Well, I actually found a solution that used less characters and was a bit faster, but it involved black magic (it involved metatable functions de-referencing themselves inside their own bodies) and it was much less readable than this one.
If anyone finds a shorter, simpler function that does the same, I'll gladly give him the answer.
Usage is simple: replace setmetatable by setindirectmetatable when you want it to "go up":
mt1 = {__tostring=function(x) return x.name or "no name" end }
mt2 = {}
setmetatable(mt2, {__index=mt1})
x = {name='x'}
y = {name='y'}
setmetatable(x, mt1)
setindirectmetatable(y, mt2) -- only change in code
print(x) -- prints "x"
print(mt2.__tostring(y)) -- prints "y"
print(y) -- prints "y"
A little word of warning: setindirectmetatable creates metamethods on mt2. Changing that behavior so a copy is made, and mt2 remains unaltered, should be trivial. But letting them set up by default is actually better for my purposes.
From my experience with Lua 5.1, metamethods are looked up in metatables using rawget(), and that's why you must copy the reference to the function into every class table you create.
See the Inheritance Tutorial on the Lua Users Wiki.

Resources