"attempt to index field '?' (a nil value)" - But can't find the cause

I’ve got yet another question. I’ve got a table called saveData and I’m putting the data from that data in another table by doing this:

local newSaveTable = saveData

And well, that’s working. After that I’m confirming if all the data is transferred by using some print statements:

 for i=1, #newSaveTable do print("") print("----------------------------------------------------------------------") print("") print("Name: " .. newSaveTable[i].name) print("Date: " .. newSaveTable[i].date) print("Amount: " .. newSaveTable[i].amount) print("Category: " .. newSaveTable[i].category) print("ID: " .. newSaveTable[i].id) print("") print("----------------------------------------------------------------------") print("") end

And like expected, all the data is transferred. After that I’m trying to filter out some items in the table. I’m trying to delete all the items that do not include the “friend” category. I do this by doing this:

 local currentScene = composer.getSceneName("current") print("Current Scene: " .. currentScene) for i=1, #newSaveTable do if newSaveTable[i].category ~= currentScene then table.remove(newSaveTable, i) end end

So in that part of code I assign currentScene and that goes as planned, nothing wrong with that. After that I’m looping through my table again like I did with all the print statements, still no problem. But the line with the if statement gives me an error:

02:32:47.100 ERROR: Runtime error 02:32:47.100 D:\PayMeBack\Code\PayMeBack\friend.lua:645: attempt to index field '?' (a nil value) 02:32:47.100 stack traceback: 02:32:47.100 D:\PayMeBack\Code\PayMeBack\friend.lua:645: in function \<D:\PayMeBack\Code\PayMeBack\friend.lua:620\> 02:32:47.100 ?: in function 'dispatchEvent' 02:32:47.100 ?: in function 'gotoScene' 02:32:47.100 D:\PayMeBack\Code\PayMeBack\main.lua:44: in main chunk

It says that I’m trying to index a nil value but I just earlier confirmed that none of the data is nil. Could someone tell me what I’m missing here?

I believe, when removing entries from a Lua table, you need to iterate backwards from the end, due to the way that Lua handles table indexing. I think that second snippet should look more like:

 local currentScene = composer.getSceneName("current") print("Current Scene: " .. currentScene) for i=#newSaveTable,1, -1 do -- note the difference here if newSaveTable[i].category ~= currentScene then table.remove(newSaveTable, i) end end

I’m trying and failing to find a reference to the veracity of the above from a developer more experienced than I. Code is untested so YMMV.

Hi Alex,

So I tried doing this:

 local currentScene = composer.getSceneName("current") print("Current Scene: " .. currentScene) for i=#newSaveTable, 1, -1 do if newSaveTable[i].category ~= currentScene then table.remove(newSaveTable, i) end end

And it appeared to be working at first sight, but something strange happened. It removed all the data in my saveData table (the original table that was assigned to the newSaveTable) that does not have the “friend” category. 

The original saveData table is a table saved in json with Rob’s module. But I’m never saving newSaveTable what so ever so I don’t get how it would be able to access my json file?

When you set up the table newSaveTable, it’s not a new table, it’s a reference to the original table. Changing data in newSaveTable changes data in saveData.

You need to deep copy the table if you want it to be a separate table containing identical data.

[lua]

local copyTable = function(object) – function to copy one table to another (not just a reference, new memory addresses)

    local lookup_table = {}

    local function _copy(object)

        if type(object) ~= “table” then

            return object

        elseif lookup_table[object] then

            return lookup_table[object]

        end

        local new_table = {}

        lookup_table[object] = new_table

        for index, value in pairs(object) do

            new_table[_copy(index)] = _copy(value)

        end

        return setmetatable(new_table, _copy(getmetatable(object)))

    end

    return _copy(object)

end

local newSaveTable = copyTable(saveData)

[/lua]

Works like a charm, thanks!

I believe, when removing entries from a Lua table, you need to iterate backwards from the end, due to the way that Lua handles table indexing. I think that second snippet should look more like:

 local currentScene = composer.getSceneName("current") print("Current Scene: " .. currentScene) for i=#newSaveTable,1, -1 do -- note the difference here if newSaveTable[i].category ~= currentScene then table.remove(newSaveTable, i) end end

I’m trying and failing to find a reference to the veracity of the above from a developer more experienced than I. Code is untested so YMMV.

Hi Alex,

So I tried doing this:

 local currentScene = composer.getSceneName("current") print("Current Scene: " .. currentScene) for i=#newSaveTable, 1, -1 do if newSaveTable[i].category ~= currentScene then table.remove(newSaveTable, i) end end

And it appeared to be working at first sight, but something strange happened. It removed all the data in my saveData table (the original table that was assigned to the newSaveTable) that does not have the “friend” category. 

The original saveData table is a table saved in json with Rob’s module. But I’m never saving newSaveTable what so ever so I don’t get how it would be able to access my json file?

When you set up the table newSaveTable, it’s not a new table, it’s a reference to the original table. Changing data in newSaveTable changes data in saveData.

You need to deep copy the table if you want it to be a separate table containing identical data.

[lua]

local copyTable = function(object) – function to copy one table to another (not just a reference, new memory addresses)

    local lookup_table = {}

    local function _copy(object)

        if type(object) ~= “table” then

            return object

        elseif lookup_table[object] then

            return lookup_table[object]

        end

        local new_table = {}

        lookup_table[object] = new_table

        for index, value in pairs(object) do

            new_table[_copy(index)] = _copy(value)

        end

        return setmetatable(new_table, _copy(getmetatable(object)))

    end

    return _copy(object)

end

local newSaveTable = copyTable(saveData)

[/lua]

Works like a charm, thanks!