Search code examples
lua

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


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)


Solution

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